Динамические конечные точки в ServiceReferences.ClientConfig
При создании приложения он часто развертывается в разных средах (test, dev, prod), и поэтому адреса конечных точек меняются. Поскольку ServiceReferences.ClientConfig построен как часть файла Silverlight.xap, его трудно изменить конечные точки после создания решения, как это часто делается с помощью web.config.
Я искал для этого немного, но я не могу понять, что лучше всего здесь, поэтому мой вопрос:
Что лучше всего подходит для динамической конфигурации адресов конечных точек wcf в silverlight?
Чтобы уточнить, в зависимости от того, на каком сервере установлено приложение (test, dev, prod), конечные точки меняются:
<endpoint
name="MyService"
address="http://testserv/MyService.svc"
binding="basicHttpBinding"
bindingConfiguration="MybasicHttpBinding"
contract="MyApp.MyService"
/>
<endpoint
name="MyService"
address="http://prodserv/MyService.svc"
binding="basicHttpBinding"
bindingConfiguration="MybasicHttpBinding"
contract="MyApp.MyService"
/>
В некотором роде мне нужен клиент silverlight, чтобы узнать, какой из них использовать, в зависимости от того, какой сервер его скомпилирован или какая сборка компилируется.
Ответы
Ответ 1
После чтения сообщения sLedgem и некоторого поиска в Google я нашел идеальное решение, чтобы заставить ServiceReferences действовать как web.config.
Прежде всего:
Создайте различные файлы вручную;
ServiceReferences.Debug.ClientConfig
ServiceReferences.Release.ClientConfig
Вы также можете добавить свой собственный, если в Visual Studio больше двух конфигураций по умолчанию.
Во-вторых:
Добавьте зависимость файла в файл Project.csproj(откройте файл проекта в текстовом редакторе):
<ItemGroup>
<None Include="Properties\AppManifest.xml" />
<Content Include="ServiceReferences.ClientConfig">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<Content Include="ServiceReferences.Debug.ClientConfig">
<DependentUpon>ServiceReferences.ClientConfig</DependentUpon>
</Content >
<Content Include="ServiceReferences.Release.ClientConfig">
<DependentUpon>ServiceReferences.ClientConfig</DependentUpon>
</Content >
</ItemGroup>
Теперь, когда вы перезагрузите проект, вы увидите, что ServiceReferences.Release.ClientConfig расширяется в обозревателе решений, а при его расширении вы увидите файл Release и Debug.
В-третьих: добавьте правила преобразования в файл проекта непосредственно перед закрытием </Project>
(снова откройте его в текстовом редакторе)
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets. -->
<UsingTask TaskName="TransformXml" AssemblyFile="$(MSBuildExtensionsPath)\Microsoft\VisualStudio\v10.0\Web\Microsoft.Web.Publishing.Tasks.dll" />
<Target Name="AfterCompile" Condition="exists('ServiceReferences.$(Configuration).ClientConfig')">
<!-- Generate transformed ServiceReferences config in the intermediate directory -->
<TransformXml Source="ServiceReferences.ClientConfig" Destination="$(IntermediateOutputPath)$(TargetFileName).ClientConfig" Transform="ServiceReferences.$(Configuration).ClientConfig" />
<!-- Force build process to use the transformed configuration file from now on. -->
<ItemGroup>
<ServiceReferencesConfigWithTargetPath Remove="ServiceReferences.ClientConfig" />
<ServiceReferencesConfigWithTargetPath Include="$(IntermediateOutputPath)$(TargetFileName).ClientConfig">
<TargetPath>$(TargetFileName).ClientConfig</TargetPath>
</ServiceReferencesConfigWithTargetPath>
</ItemGroup>
</Target>
Что он делает, так это посмотреть в соответствующем файле servicereferences, в зависимости от вашей конфигурации, и скопировать/заменить код с помощью той же библиотеки TransformXML, которую использует web.config.
Пример:
в моем ServiceReferences.ClientConfig у меня есть следующий код:
<endpoint name="ICatalogueService"
address="address"
binding="basicHttpBinding"
bindingConfiguration="My_basicHttpBinding"
contract="Services.ServiceInterfaces.ICatalogueService"/>
ServiceReferences.Release.ClientConfig:
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
<system.serviceModel>
<client>
<endpoint
name="ICatalogueService"
address="http://server/Services/CatalogueService.svc"
binding="basicHttpBinding"
bindingConfiguration="My_basicHttpBinding"
contract="Services.ServiceInterfaces.ICatalogueService"
xdt:Transform="Replace" xdt:Locator="Match(name)" />
</client>
<extensions />
</system.serviceModel>
</configuration>
Как вы можете видеть, конечная точка будет заменена, а совпадение выполняется с атрибутом имени.
Если у вас есть какие-либо вопросы, дайте мне знать:)
Ответ 2
Отличное решение проблемы
Я не мог получить раздел <ItemGroup></ItemGroup>
, чтобы эффективно работать в моем решении.
Я удалил его и добавил следующий script к моему событию Prebuild в проекте:
del $(ProjectDir)ServiceReferences.ClientConfig;
copy $(ProjectDir)ServiceReferences.$(ConfigurationName).ClientConfig $(ProjectDir)ServiceReferences.ClientConfig;
Ответ 3
Вы можете сделать это во время выполнения, используя конструктор клиента WCF в SL, который принимает имя конфигурации конечной точки и адрес. Конфигурация конечной точки - это просто "MyService" в вашем примере. Аргумент адреса, который вы предоставляете, будет переопределять тот, который включен в ClientConfig.
Один из способов расчета адреса вашего сервиса во время выполнения из SL (я не гарантирую, что он будет работать в каждой конфигурации среды):
- Вычислить корень вашего сайта, например. найдя общую часть
Application.Current.Host.Source.AbsoluteUri и
HtmlPage.Document.DocumentUri.AbsoluteUri. В основном, вы принимаете
символов с начала более короткого пути, если они
сопоставьте символы, не учитывающие регистр, на другом пути.
- Добавить относительный путь к сервисам, если они есть (это, похоже, не так).
- Добавить MyService.svc
Дополнительная информация:
Это может показаться сложным, если у вас много сервисов, но все это может быть хорошо реорганизовано и с помощью Unity сделать его очень простым в использовании для любой службы. Например, я использую вспомогательную функцию, которая регистрирует клиента службы, и он вызывает это: ServiceHelper.RegisterService < MyServiceContractClient, IMyServiceContract > ( "MyService" ); Когда мне нужно создать экземпляр сервисного клиента, я просто разрешаю тип MyServiceContractClient с Unity, который использует конструктор впрыска для создания нового экземпляра моего сервиса, который уже настроен правильно. Он также может обрабатывать ситуацию с HTTPS. Дайте мне знать, если вам нужна дополнительная информация об этом.
Ответ 4
Посмотрите здесь:
http://weblogs.asp.net/srkirkland/archive/2009/10/13/common-web-config-transformations-with-visual-studio-2010.aspx
то здесь
http://www.funkymule.com/post/2010/03/08/XML-Transform-on-Silverlight-ClientConfig-Files.aspx
Он использует тот же принцип, что и для преобразований web.config(т.е. web.config изменяется в зависимости от конфигурации, которую вы компилируете (например, release, debug), чтобы serviceref.config был изменен в соответствии с вашей прихоти при компиляции работает шарм
Ответ 5
Ответ randoms - это пятно, за исключением ОДНОЙ маленькой вещи. Не отмечайте .Debug.ClientConfig и .Release.ClientConfig как "Содержимое". Отметьте их как "Нет". Таким образом, ваши .Debug.ClientConfig и .Release.ClientConfig не помещаются в ваш .xap файл. Вот что в моем файле проекта Silverilght (и он отлично работает):
<Content Include="ServiceReferences.ClientConfig">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
<None Include="ServiceReferences.DEV.ClientConfig">
<DependentUpon>ServiceReferences.ClientConfig</DependentUpon>
</None>
<None Include="ServiceReferences.TEST.ClientConfig">
<DependentUpon>ServiceReferences.ClientConfig</DependentUpon>
</None>
<None Include="ServiceReferences.PROD.ClientConfig">
<DependentUpon>ServiceReferences.ClientConfig</DependentUpon>
</None>