Упрощение настройки WCF - PullRequest
       20

Упрощение настройки WCF

14 голосов
/ 18 сентября 2008

У меня есть набор веб-служб WCF, к которым динамически подключается настольное приложение.

Моя проблема в действительно подробных настройках конфигурации, необходимых для работы WCF. Чтобы заставить работать SSL, нужны пользовательские настройки. Чтобы заставить работать MTOM или что-то еще, требуется больше. Вы хотите сжатие? Здесь мы идем снова ...

WCF действительно мощный - вы можете использовать множество различных способов подключения, но все, похоже, требуют много подробных настроек. Если хост и клиент не совпадают идеально, вам трудно расшифровать ошибки.

Я хочу сделать настольное приложение намного проще в настройке - в идеале, это своего рода автоматическое обнаружение. Пользователи настольного приложения должны просто ввести URL-адрес, а он сделает все остальное.

Кто-нибудь знает хороший способ сделать это?

Я знаю, что Visual Studio может настроить конфигурацию для вас, но я хочу, чтобы приложение для настольных компьютеров могло делать это на основе широкого спектра различных настроек сервера.

Я знаю, что инструменты VS могут использоваться извне, но я ищу пользователей настольных приложений, чтобы они не были экспертами WCF. Я знаю, что М.С. сделал это намеренно слишком сложным.

Есть ли какой-либо способ, механизм, сторонняя библиотека или что-нибудь, чтобы сделать возможным автоматическое обнаружение настроек WCF?

Ответы [ 3 ]

9 голосов
/ 19 сентября 2008

Вся информация о конечной точке доступна в метаданных службы, вы можете написать клиенту, который изучит метаданные службы и настроит клиента. Для примера кода вы можете посмотреть на этот превосходный Mex Explorer от Juval Lowy.

1 голос
/ 02 декабря 2009

Теперь есть другой способ сделать это, который не был доступен, когда я задал оригинальный вопрос. Microsoft теперь поддерживает REST для служб WCF.

  • Недостатком использования REST является то, что вы потеряете WSDL.
  • Потенциал минимален, и ваши контрактные интерфейсы WCF все равно будут работать!

Вам понадобится новая ссылка на System.ServiceModel.Web

Отметьте свои операции с помощью WebInvoke или WebGet

//get a user - note that this can be cached by IIS and proxies
[WebGet]
User GetUser(string id )

//post changes to a user
[WebInvoke]
void SaveUser(string id, User changes )

Добавить их на сайт легко - добавьте файл .svc:

<%@ServiceHost 
   Service="MyNamespace.MyServiceImplementationClass" 
   Factory="System.ServiceModel.Activation.WebServiceHostFactory" %>

Заводская линия сообщает ASP.net, как активировать конечную точку - вам вообще не нужна конфигурация на стороне сервера!

Тогда построение вашего ChannelFactory практически не изменится, за исключением того, что вам больше не нужно указывать конечную точку (или автоматически обнаруживать одну, как у меня в других ответах)

var cf = new WebChannelFactory<IMyContractInterface>();
var binding = new WebHttpBinding();

cf.Endpoint.Binding = binding;
cf.Endpoint.Address = new EndpointAddress(new Uri("mywebsite.com/myservice.svc"));
cf.Endpoint.Behaviors.Add(new WebHttpBehavior());

IMyContractInterface wcfClient = cf.CreateChannel();

var usr = wcfClient.GetUser("demouser");
// and so on...

Обратите внимание, что я не указал или не обнаружил конфигурацию клиента - локальная конфигурация не требуется!

Другим большим преимуществом является то, что вы можете легко переключиться на сериализацию JSON - которая позволяет использовать те же службы WCF, что и Java, ActionScript, Javascript, Silverlight или все, что может легко обрабатывать JSON и REST.

1 голос
/ 19 сентября 2008

Спасибо, это был полезный код (+1).

Это немного более грязно, хотя и содержит некоторые ошибки (например, проверки с учетом регистра, которых не должно быть), имеет множество функций пользовательского интерфейса, которые мне не нужны, и повторяет много кода. *

Я извлек из него действительный механизм обнаружения, переписал его и почти заставил его работать (подключается, но требует некоторой перебора).

Сначала некоторые полезные функции, используемые основным методом:

/// <summary>If the url doesn't end with a WSDL query string append it</summary>
static string AddWsdlQueryStringIfMissing( string input )
{
    return input.EndsWith( "?wsdl", StringComparison.OrdinalIgnoreCase ) ?
        input : input + "?wsdl";
}

/// <summary>Imports the meta data from the specified location</summary>
static ServiceEndpointCollection GetEndpoints( BindingElement bindingElement, Uri address, MetadataExchangeClientMode mode )
{
    CustomBinding binding = new CustomBinding( bindingElement );
    MetadataSet metadata = new MetadataExchangeClient( binding ).GetMetadata( address, mode );
    return new WsdlImporter( metadata ).ImportAllEndpoints();
}

Затем метод, который пытается подключиться другим способом и возвращает конечные точки:

public static ServiceEndpointCollection Discover( string url )
{
    Uri address = new Uri( url );
    ServiceEndpointCollection endpoints = null;

    if ( string.Equals( address.Scheme, "http", StringComparison.OrdinalIgnoreCase ) )
    {
        var httpBindingElement = new HttpTransportBindingElement();

        //Try the HTTP MEX Endpoint
        try { endpoints = GetEndpoints( httpBindingElement, address, MetadataExchangeClientMode.MetadataExchange ); }
        catch { }

        //Try over HTTP-GET
        if ( endpoints == null )
            endpoints = GetEndpoints( httpBindingElement,
                new Uri( AddWsdlQueryStringIfMissing( url ) ), MetadataExchangeClientMode.HttpGet );
    }
    else if ( string.Equals( address.Scheme, "https", StringComparison.OrdinalIgnoreCase ) )
    {
        var httpsBindingElement = new HttpsTransportBindingElement();

        //Try the HTTPS MEX Endpoint
        try { endpoints = GetEndpoints( httpsBindingElement, address, MetadataExchangeClientMode.MetadataExchange ); }
        catch { }

        //Try over HTTP-GET
        if ( endpoints == null )
            endpoints = GetEndpoints( httpsBindingElement,
                new Uri( AddWsdlQueryStringIfMissing( url ) ), MetadataExchangeClientMode.HttpGet );
    }
    else if ( string.Equals( address.Scheme, "net.tcp", StringComparison.OrdinalIgnoreCase ) )
        endpoints = GetEndpoints( new TcpTransportBindingElement(), 
            address, MetadataExchangeClientMode.MetadataExchange );

    else if ( string.Equals( address.Scheme, "net.pipe", StringComparison.OrdinalIgnoreCase ) )
        endpoints = GetEndpoints( new NamedPipeTransportBindingElement(), 
            address, MetadataExchangeClientMode.MetadataExchange );

    return endpoints;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...