Кроссплатформенный метод RESTful WCF, передача и возврат массива байтов

Так просто в теории, но я никогда не был мастером настройки WCF. Я пытаюсь сделать следующее: у меня есть метод WCF, который соответствует этой подписи:

[OperationContract]
[WebInvoke(Method = "POST")]
Stream PostPackets(Stream rawPackets);

Все, о чем я действительно забочусь, это получить массив байтов с устройства Android/iPhone/Blackberry/любого другого типа в мою службу wcf, обработать массив и затем отправить обратно другой массив байтов. Мне все равно, это может выглядеть так:

[OperationContract]
[WebInvoke(Method = "POST")]
byte[] PostPackets(byte[] rawPackets);

Хотя все примеры, которые я вижу, похоже, используют Stream.

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

1- Я предполагаю, что мне нужно использовать webHttpBinding, чтобы сделать эту службу RESTful. Это правильно? Если да, можете ли вы указать мне образец конфигурации?

2 - (И это абсолютно то, что я нигде не могу найти!) Мне нужно быть уверенным, что это не станет огромной проблемой для разработчиков устройств. Можете ли вы показать мне примеры устройств Android и iPhone, использующих службу RESTful И (очень важно), как они будут отправлять массив байтов в мою службу?

Пожалуйста, простите мой нубизм... Конфигурация WCF — это одна из тех вещей, которыми мне не приходится заниматься каждый день. Как только я разобрался со своей конфигурацией, я обычно иду дальше и никогда не трогаю ее до следующего проекта (который может занять очень много времени). Пожалуйста помоги!

ОБНОВЛЕНИЕ

Мой коллега предложил использовать обработчики http вместо wcf. Нам действительно нужно прибегать к этому?
например:

public void ProcessPackets (HttpContext context) 

ОБНОВЛЕНИЕ 2:

Мне интересно, есть ли способ сделать это без JSON? Есть ли недостаток/альтернатива публикации массива как типа «текст/обычный»?


person saml    schedule 21.01.2013    source источник


Ответы (2)


Может быть, этот простой (и рабочий пример) может помочь

СЕРВЕР

void StartServer()
{
    Task.Factory.StartNew(() =>
    {
        WebServiceHost host = new WebServiceHost(typeof(MyService), new Uri("http://0.0.0.0:80/MyService/"));
        host.Open();
    });
}

[ServiceContract]
public class MyService
{
    [OperationContract]
    [WebInvoke(
        RequestFormat = WebMessageFormat.Json,
        ResponseFormat = WebMessageFormat.Json,
        BodyStyle = WebMessageBodyStyle.WrappedRequest)]
    public byte[] PostPackets(byte[] rawPackets)
    {
        rawPackets[0] = 99;
        return rawPackets;
    }
}

КЛИЕНТ

<html>
<script src='jquery-1.8.3.min.js'></script>

<body>
<script>
         $(document).ready(function () {
            $.ajax({
                type: "POST",
                contentType: "application/json",
                url: "/MyService/PostPackets",
                data: JSON.stringify({rawPackets:[65,66,67]}), 
                dataType: "text",
                success: function (data) {
                    //var div = $("#test").empty();
                    //$("#test").html(data.d);
                    alert('success');
                },
                error: function (XMLHttpRequest, textStatus, errorThrown) {
                    alert('error');
                }
            });
        });
</script>
</body>
</html>
person I4V    schedule 21.01.2013
comment
Спасибо это хорошо! Но мне нужно быть уверенным, что это возможно и с Android/blackberry/iphone. - person saml; 21.01.2013
comment
Кроме того, в приведенном выше примере вы также можете опубликовать, как будет выглядеть файл web.config для вашей конфигурации wcf? Спасибо - person saml; 21.01.2013
comment
Как я уже сказал, пожалуйста, простите меня за то, что во всех смыслах и целях я новичок в сервисе wcf RESTful, но если вы посмотрите здесь: codeproject.com/Articles/105273/ разве мне не нужно настраивать файл web.config, как в шаге 6? - person saml; 21.01.2013
comment
@saml Чтобы запустить приведенный выше код, вы можете создать приложение любого типа (например, winforms, Console). Просто вызовите StartServer где-нибудь в своем коде, и все готово. Я не могу придумать более простой способ создания службы RESTful. - person I4V; 21.01.2013
comment
Вау, если это работает в моей текущей среде (служба wcf в настоящее время размещена как служба Windows), то вы только что сэкономили мне много времени, борясь с файлом конфигурации для поддержки нескольких типов привязки. Кстати, этот метод поддерживает ssl? - person saml; 21.01.2013
comment
Кроме того, я предполагаю, что 0.0.0.0:80/MyService следует заменить на: mydomainname/MyService ? - person saml; 21.01.2013
comment
@saml для ssl просто замените http на https (при условии, что вы уже выполнили работу, связанную с сертификатом и т. д.) - person I4V; 21.01.2013
comment
@saml 0.0.0.0 используется, чтобы разрешить прием соединений из любого места. Если вы напишете его как mydomain/MyService, только компьютеры из mydomain смогут получить доступ к этой службе. - person I4V; 21.01.2013
comment
Кажется слишком хорошим, чтобы быть правдой, я не могу дождаться, чтобы попробовать это. Я не думаю, что вы знаете, как использовать эту услугу из приложения для устройства Android, не так ли (не веб-приложение)? - person saml; 21.01.2013
comment
@saml Извините, нет. Но я помню пост. Позвольте мне искать. - person I4V; 21.01.2013
comment
@saml, возможно, этот код может помочь stackoverflow.com/questions/13165533/ - person I4V; 21.01.2013
comment
Отлично, я попробую и сообщу вам в ближайшее время! - person saml; 21.01.2013
comment
К сожалению, это не сработало. Я получаю сообщение об ошибке Служба не может быть запущена. System.InvalidOperationException: служба MyService не имеет конечных точек приложения (не инфраструктуры). Это может быть связано с тем, что для вашего приложения не был найден файл конфигурации, или с тем, что в файле конфигурации не удалось найти элемент службы, соответствующий имени службы, или с тем, что в элементе службы не были определены конечные точки. - person saml; 27.01.2013

В итоге решение было следующим. (Это было действительно очень просто)

Сторона обслуживания:

[ServiceContract]
public interface IMyService
{
    [OperationContract]
    [WebInvoke(Method = "POST",
        BodyStyle = WebMessageBodyStyle.Wrapped,
        UriTemplate="TestMethod/")]
    Stream TestMethod(Stream input);

}

public class MyService: IMyService
{
    Stream IMyService.TestMethod(Stream input)
    {
        byte[] buffer = new byte[10000];
        int bytesRead, totalBytesRead = 0;
        this.currentResponseOffset = 0;
        do
        {
            bytesRead = input.Read(buffer, 0, buffer.Length);
            totalBytesRead += bytesRead;
        } while (bytesRead > 0);

        input.Close();

        return new MemoryStream(buffer, 0, totalBytesRead);
    }
}

С конфигурацией, которая выглядит так:

<services>
  <service name="MyService" >
    <host>
      <baseAddresses>
        <add baseAddress="http://localhost:8732/Design_Time_Addresses/MyService/" />
        <add baseAddress="net.tcp://localhost:4504/Design_Time_Addresses/MyService/" />
      </baseAddresses>
    </host>
    <endpoint address="MyTCPService" binding="netTcpBinding" contract="IMyTCPService">
    </endpoint>

    <endpoint address="MyHTTPService" binding="webHttpBinding" behaviorConfiguration="web" contract="IMyService"></endpoint>  

    <endpoint address="mex" binding="mexTcpBinding" contract="IMetadataExchange" />
    <endpoint address="mex"  binding="mexHttpBinding" contract="IMetadataExchange"/>
    <!--<endpoint binding="mexHttpsBinding" bindingConfiguration="" contract="IMetadataExchange" />-->
  </service>
</services>
<behaviors>
   <endpointBehaviors>
    <behavior name="web">
      <webHttp />
    </behavior>
  </endpointBehaviors>
</behaviors>

Я смог протестировать его с помощью клиента .net, хотя весь смысл этого поста заключался в том, чтобы узнать, как сделать его кроссплатформенным. Думаю скоро увидим! Спасибо @I4V за вашу помощь, это очень ценно.

person saml    schedule 29.01.2013