Поддержка Mtom и Text как MessageEncoding в WCF

У меня есть служба WCF, которая имеет метод со следующей подписью:

object GetCommand(Guid apiKey, SocialService service, string name, object argument);

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

В любом случае, я передаю объект, который содержит следующее свойство:

public byte[] Photo { get; set; }

Чтобы включить большие сообщения, я бы хотел начать использовать Mtom, в то время как ранее я использовал обычный текст в качестве типа MessageEncoding.

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

Мой вопрос: возможно ли по-прежнему использовать обычный текст в качестве MessageEncoding (по умолчанию для существующих клиентов) и предлагать кодирование Mtom одновременно?

Я пробовал кое-что с конфигурацией, например, определение нескольких конечных точек с разными конфигурациями связывания, но я не могу заставить его работать:

сервер

<system.serviceModel>
    <bindings>
        <basicHttpBinding>
            <binding name="BasicHttpTextBinding_SocialProxy" />
            <binding name="BasicHttpMtomBinding_SocialProxy" maxReceivedMessageSize="5242880" messageEncoding="Mtom">
                <readerQuotas maxStringContentLength="655360" maxArrayLength="1310720" maxNameTableCharCount="1310720" maxBytesPerRead="327680" />
            </binding>
        </basicHttpBinding>
    </bindings>
    <services>
        <service name="SocialProxyService">
            <endpoint name="BasicEndpoint_SocialProxy" address="" contract="InfoCaster.SocialProxy.ISocialProxy" binding="basicHttpBinding" bindingConfiguration="BasicHttpTextBinding_SocialProxy" />
            <endpoint name="MtomEndpoint_SocialProxy" address="" contract="InfoCaster.SocialProxy.ISocialProxy" binding="basicHttpBinding" bindingConfiguration="BasicHttpMtomBinding_SocialProxy" />
        </service>
    </services>
    <behaviors>
        <serviceBehaviors>
            <behavior>
                <!-- To avoid disclosing metadata information, set the value below to false and remove the metadata endpoint above before deployment -->
                <serviceMetadata httpGetEnabled="true" />
                <!-- To receive exception details in faults for debugging purposes, set the value below to true. Set to false before deployment to avoid disclosing exception information -->
                <serviceDebug includeExceptionDetailInFaults="true" />
            </behavior>
        </serviceBehaviors>
    </behaviors>
    <serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
</system.serviceModel>

клиент

<system.serviceModel>
    <bindings>
        <basicHttpBinding>
            <binding name="BasicHttpBinding_SocialProxy" messageEncoding="Mtom" />
        </basicHttpBinding>
    </bindings>
    <client>
        <endpoint address="http://socialproxy.local/socialproxy.svc"
            binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding_SocialProxy"
            contract="Webservice.SocialProxy" name="BasicHttpBinding_SocialProxy" />
    </client>
</system.serviceModel>

Проблема в следующем:

Если я не установлю Mtom messageEncoding @ клиент, все работает через обычный текст. Но когда я настрою его на использование Mtom, я получу исключение:

The remote server returned an error: (415) Cannot process the message because the content type 'multipart/related; type="application/xop+xml";start="<http://tempuri.org/0>";boundary="uuid:65a6b418-8eb3-4c76-b4c0-ea3486a56892+id=2";start-info="text/xml"' was not the expected type 'text/xml; charset=utf-8'..

Кто-нибудь может мне помочь?:-)

1 ответ

Решение

Если вы хотите добавить новую конечную точку (для новых клиентов), эта конечная точка должна находиться по другому адресу. Так как вы не получили никакой ошибки, я полагаю, у вас неверное имя в name атрибут <service> элемент. Помните, что атрибут name должен содержать полное имя класса обслуживания. Если ваш класс обслуживания находится в пространстве имен InfoCaster.SocialProxy, ваша конфигурация сервиса должна быть определена как ниже:

<services> 
    <service name="InfoCaster.SocialProxy.SocialProxyService"> 
        <endpoint name="BasicEndpoint_SocialProxy" address="" contract="InfoCaster.SocialProxy.ISocialProxy" binding="basicHttpBinding" bindingConfiguration="BasicHttpTextBinding_SocialProxy" /> 
        <endpoint name="MtomEndpoint_SocialProxy" address="newClients" contract="InfoCaster.SocialProxy.ISocialProxy" binding="basicHttpBinding" bindingConfiguration="BasicHttpMtomBinding_SocialProxy" /> 
    </service> 
</services> 

И клиенты будут иметь что-то вроде

<client>  
    <endpoint address="http://socialproxy.local/socialproxy.svc/newClients"  
        binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding_SocialProxy"  
        contract="Webservice.SocialProxy" name="BasicHttpBinding_SocialProxy" />  
</client>  

Теперь, если вам нужна одна конечная точка, которая может поддерживать как текст, так и MTOM таким образом, чтобы клиенты, отправляющие текст, получали текстовый ответ, а клиенты, отправляющие MTOM, получали ответ MTOM обратно, вы все равно можете это сделать. Вам понадобится пользовательский кодировщик, и я написал его в посте по адресу http://blogs.msdn.com/b/carlosfigueira/archive/2011/02/16/using-mtom-in-a-wcf-custom-encoder.aspx.

Другие вопросы по тегам