2016-03-03 3 views
2

Я успешно создал самостоятельный WCF-моносервис на малиновой jessie, и он работает (почти).mono-service WCF OPTIONS на rasbian

Версии

  • Mono версии JIT компилятор 4.2.1
  • Raspbian GNU/Linux 8 \ п \ л

Проблема заключается в том, что Chrome веб-приложения не могут потреблять его, так как он не отвечает на любой запрос OPTIONS. Запрос остается в «ожидающий», пока я не убью службу.

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

Установки, которые у меня есть.

app.config

<startup> 
    <supportedRuntime version="v4.5" sku=".NETFramework,Version=v4.5" /> 
</startup> 
<system.serviceModel> 
    <services> 
    <service name="AspaDeviceControlCenter.Fp550Module.Fp550Module"> 
     <endpoint address="http://localhost:8111/json/fp550/" binding="webHttpBinding" behaviorConfiguration="jsonEndpointBehaviour" contract="AspaDeviceControlCenter.Fp550Module.IFp550Module"/> 
    </service> 
    </services> 
    <behaviors> 
    <serviceBehaviors> 
     <behavior> 
     <serviceMetadata httpGetEnabled="true" /> 
     </behavior> 
    </serviceBehaviors> 
    <endpointBehaviors> 
     <behavior name="jsonEndpointBehaviour"> 
     <webHttp/> 
     <corsEndpointBehaviorExtension/> 
     </behavior> 
     <behavior name="webscriptBehavior"> 
     <enableWebScript/> 
     </behavior> 
    </endpointBehaviors> 
    </behaviors> 
    <serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true"/> 
</system.serviceModel> 
<system.webServer> 
    <modules runAllManagedModulesForAllRequests="true"/> 
    <directoryBrowse enabled="true"/> 
</system.webServer> 
<extensions> 
    <behaviorExtensions> 
    <add name="corsEndpointBehaviorExtension" type="AspaDeviceControlCenter.Service.Hosting.CorsEndpointBehaviorExtension, AspaDeviceControlCenter.Service"/> 
    </behaviorExtensions> 
</extensions> 

Я использовал EndpoinBehaviorExtension решение от enable-cors.org для добавления требуется «Alow» заголовки в любой запрос OPTIONS, но точка останова там не срабатывает для запросов OPTIONS, только GET и POST

расширение фактическая часть

public class CorsEndpointBehaviorExtension : BehaviorExtensionElement, IEndpointBehavior 
{ 
    /*some empty methods*/ 

    public void ApplyDispatchBehavior(ServiceEndpoint endpoint, System.ServiceModel.Dispatcher.EndpointDispatcher endpointDispatcher) 
    { 
     var requiredHeaders = new Dictionary<string, string>(); 

     //requiredHeaders.Add("Access-Control-Allow-Origin", "*"); 
     requiredHeaders.Add("Access-Control-Request-Method", "POST,GET,PUT,DELETE,OPTIONS"); 
     requiredHeaders.Add("Access-Control-Allow-Headers", "Accept,Origin,Authorization,X-Requested-With,Content-Type,X-Tenant"); 

     endpointDispatcher.DispatchRuntime.MessageInspectors.Add(new CorsDispatchMessageInspector(requiredHeaders)); 
    } 

Теперь та часть, которая должна помочь и где я думаю, что проблема, с re является более глубоким, возможно, конфигурацией ОС, но я не эксперт по Linux.

public class CorsDispatchMessageInspector: IDispatchMessageInspector 
{ 
    Dictionary<string, string> requiredHeaders; 

    public CorsDispatchMessageInspector(Dictionary<string, string> headers) 
    { 
     requiredHeaders = headers ?? new Dictionary<string, string>(); 
    } 

    public object AfterReceiveRequest(ref Message request, IClientChannel channel, InstanceContext instanceContext) 
    { 
     return null; 
    } 
    public void BeforeSendReply(ref Message reply,object correlationState) 
    { 

     var httpHeader = reply.Properties["httpResponse"] as HttpResponseMessageProperty; 
     foreach (var item in requiredHeaders) 
     { 
      httpHeader.Headers.Add(item.Key, item.Value); 
     }   
    } 
} 

Оба AfterReceiveRequest и BeforeSendReply имеет контрольные точки, и они ломаются, когда я отправить POST/GET, но не тогда, когда метод запроса OPTIONS

Контракт интерфейс сервиса. У меня есть много разных контрактов на работу, определенных для проверки того, что я нашел в Интернете до сих пор. Ни один из них не ответил на запрос OPTIONS.

[ServiceContract] 
public interface IFp550Module : IControlCenterModule 
{ 
    [OperationContract] 
    bool Init(); 

    [OperationContract] 
    [WebInvoke(Method = "POST", RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json, BodyStyle = WebMessageBodyStyle.Wrapped)] 
    string Open(/*int port, string settings*/); 

    [OperationContract] 
    [WebInvoke(Method = "*", RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json, BodyStyle = WebMessageBodyStyle.Wrapped)] 
    string Version(); 

    [OperationContract] 
    [WebInvoke(Method = "OPTIONS", UriTemplate="*", RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json, BodyStyle = WebMessageBodyStyle.Wrapped)] 
    bool GetOptions(); 
} 

В процессе работы не происходит перехват обратных вызовов.

var host = new ServiceHost(module); 
_serviceHosts.Add(host); 
host.Faulted += OnFaulted; 
host.UnknownMessageReceived += OnUnknownMessageReceived; 
host.Opening += module.ServiceStarting; 
host.Closing += module.ServiceClosing; 
host.Open(); 

Я также попробовал свои собственные CustomTextMessageEncoder: MessageEncoder и общественное переопределение Сообщение метод ReadMessage точки останова был подбит только для GET/POST. Насколько глубоко я должен ударить, что точка останова запроса OPTIONS? Или, может быть, это просто какой-то флаг где-то в моносервисе.

Также, когда я останавливаю свое обслуживание, все ожидающие запросы параметров возвращают сетевую ошибку.

И когда я запускаю запрос, а затем отправляю любой запрос (включая ОПЦИИ), в выводе приложения появляется сообщение «Thread started: # 16», поэтому кажется, что запрос OPTIONS достигает «уровня приложения».

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

Сообщите мне, если я пропущу что-то. Я использую этот вопрос в качестве своего последнего средства.

ответ

2

ОК, я устал искать «моностандартные методы запроса», и я обнаружил, что это связано с ошибкой, зарегистрированной в mono-bug-tracker. Я обновлю этот ответ, если найду обходной путь.

Я искал способ повторной реализации прослушиваемой части.

EDIT: Я исправил свою проблему. Мне не удалось перекомпилировать весь моно с его зависимостями, поэтому я только перекомпилировал System.ServiceModel.dll и заменил оригинал на новый в папке mono GAC, папке System.ServiceModel. Новая dll была загружена и изменения были приняты.

Изменение было в HttpReplyChannel.cs

if (ctxi.Request.HttpMethod == "POST" || ctxi.Request.HttpMethod == "PUT") 
    msg = CreatePostMessage (ctxi); 
else if (ctxi.Request.HttpMethod == "GET" || ctxi.Request.HttpMethod == "DELETE" || ctxi.Request.HttpMethod == "OPTIONS") 
    msg = Message.CreateMessage (MessageVersion.None, null); 

Я добавил дополнительные методы, до изменения, была только GET и POST.

Теперь моя служба смогла получить запросы параметров и добавить к нему необходимые заголовки с MessageInspector.

Смежные вопросы