2015-05-19 14 views
15

Mam relaksującego usługę WWW WCF z następującymi API:WebGet bez parametrów lub UriTemplate zawodzi

[WebGet(ResponseFormat = WebMessageFormat.Json)] 
MyResponseContract GetFileInfo(); 

Kiedy próbuje uderzyć punkt końcowy (używając SoapUI) Widzę następujący komunikat o błędzie:

Serwer napotkał błąd podczas przetwarzania żądania. Proszę zobaczyć stronę pomocy serwisowej , aby skonstruować prawidłowe żądania do usługi.

Mam SOAPUI ustawiony na trafienie go za pomocą wywołania metody GET. Po przełączeniu go na test POST bez treści, kończy się niepowodzeniem z następującym komunikatem:

Metoda niedozwolona.

To ma sens: nie można trafić w GET za pomocą POST. Więc aktualizowane mój kod w następujący sposób:

[WebInvoke(ResponseFormat = WebMessageFormat.Json)] 
MyResponseContract GetFileInfo(); 

A teraz wzywam go z SoapUI z metody POST i to działa. Ciekawy. Więc teraz zmienić swój kod w następujący sposób:

[WebInvoke(ResponseFormat = WebMessageFormat.Json, Method = "GET")] 
MyResponseContract GetFileInfo(); 

Widziałem w kilku stanowisk, które jest w zasadzie odpowiednikiem atrybutu WebGet. To też nie działa.

Moje pytanie brzmi: dlaczego to nie działa jako WebGet, mimo że nie akceptuję parametrów lub używania niestandardowego UriTemplate?

adres URL staram się trafić go (jest obsługiwana lokalnie w IIS) wynosi:

http://localhost/Utilities/API/GetFileInfo

Aktualizacja Biorąc pod uwagę poniższe komentarze i odpowiedzi na pytania, ja wciąż do czynienia z ten problem. Kilka dodatkowych szczegółów.

My Web-warstwowa web.config

<?xml version="1.0"?> 
<configuration> 
    <system.web> 
    <compilation debug="true" targetFramework="4.0" /> 
    <customErrors mode="Off" /> 
    </system.web> 
    <system.serviceModel> 
    <serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" /> 
    <standardEndpoints> 
     <webHttpEndpoint> 
     <standardEndpoint name="" helpEnabled="true" automaticFormatSelectionEnabled="true" maxReceivedMessageSize="10000000" /> 
     </webHttpEndpoint> 
    </standardEndpoints> 
    <behaviors> 
     <endpointBehaviors> 
     <behavior name="exampleBehavior"> 
      <callbackDebug includeExceptionDetailInFaults="true" /> 
      <enableWebScript /> 
      <webHttp helpEnabled="true" /> 
     </behavior> 
     </endpointBehaviors> 
    </behaviors> 
    <bindings> 
     <webHttpBinding> 
     <binding name="WebHttpBinding" maxReceivedMessageSize="10000000" /> 
     </webHttpBinding> 
    </bindings> 
    <client>  
     <endpoint address="http://LOCALHOST/Utilities.AppService/API" 
       binding="webHttpBinding" bindingConfiguration="WebHttpBinding" 
       contract="Utilities.Common.API.IMyApi" 
       behaviorConfiguration="exampleBehavior" /> 
    </client> 
    </system.serviceModel> 
</configuration> 

Moja aplikacja dwuwarstwowa web.config:

<?xml version="1.0" encoding="utf-8"?> 
<configuration> 
    <system.web> 
    <compilation debug="true" targetFramework="4.0" /> 
    <customErrors mode="Off" /> 
    </system.web> 
    <system.serviceModel> 
    <serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" /> 
    <standardEndpoints> 
     <webHttpEndpoint> 
     <standardEndpoint name="" helpEnabled="true" automaticFormatSelectionEnabled="true" maxReceivedMessageSize="10000000" /> 
     </webHttpEndpoint> 
    </standardEndpoints> 
    </system.serviceModel> 
    <system.webServer> 
    <modules runAllManagedModulesForAllRequests="true" /> 
    <handlers> 
     <remove name="ExtensionlessUrlHandler-Integrated-4.0" /> 
     <add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="GET,HEAD,POST,DEBUG,PUT,DELETE" type="System.Web.Handlers.TransferRequestHandler" resourceType="Unspecified" requireAccess="Script" preCondition="integratedMode,runtimeVersionv4.0" /> 
    </handlers> 
    </system.webServer> 
</configuration> 

Mój interfejs usługi

[ServiceContract(Namespace = "API")] 
public interface IMyApi 
{  
    [WebGet] 
    MyResponseContract GetFileInfo(); 
} 

Moja implementacja web-warstwa

[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Required)] 
[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single, ConcurrencyMode = ConcurrencyMode.Multiple)] 
public class MyApiWebService : ClientBase<IMyApi>, IMyApi 
{ 
    public MyResponseContract GetFileInfo() 
    { 
     return Channel.GetFileInfo(); 
    } 
} 

Moja implementacja aplikacji warstwy

[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Required)] 
[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single, ConcurrencyMode = ConcurrencyMode.Multiple)] 
public class MyApiAppService : IMyApi 
{ 
    public MyResponseContract GetFileInfo() 
    { 
     return new MyResponseContract(); 
    } 
} 

My Web-warstwowa Global.asax:

protected void Application_Start(object sender, EventArgs e) 
    { 
     RouteTable.Routes.Add(new ServiceRoute("API", new WebServiceHostFactory(), typeof(MyApiWebService))); 
    } 

Moja aplikacja warstwy globalnej.asax:

protected void Application_Start(object sender, EventArgs e) 
    { 
     RouteTable.Routes.Add(new ServiceRoute("API", new WebServiceHostFactory(), typeof(MyApiAppService))); 
    } 

Nie jestem pewien, ile bardziej szczegółowo mogę zapewnić. Jak widać, biorąc pod uwagę dostarczone rozwiązania, zaimplementowałem wszystko, co zasugerowałem bezskutecznie. Niezależnie od tego, czy próbuję użyć tej metody WebGet, umieszczając adres URL usługi warstwy sieci Web w przeglądarce, lub używając SOAPUI, lub próbując trafić ją testem jednostki C# za pomocą klienta usługi, nie mogę użyć WebGet. Jeszcze raz dziękuję za twoją pomoc.

Co ciekawe, działa URL warstwy aplikacji. Ale warstwa internetowa nie. Więc:

localhost/Utilities.AppService/API/GetFileInfo

prace, natomiast

localhost/Utilities.WebService/API/GetFileInfo

nie.

+0

Jak masz dostępu do niego - jak próbki URI? A żeby było jasne, ostatnia też nie działała? –

+0

Zaktualizowane pytanie z wymaganymi szczegółami. –

+0

Czy używasz 'WebHttpBinding'? –

Odpowiedz

5

To może nie było oczywiste, dopóki nie zaktualizowałem się niedawno, ale mam dwie usługi RESTful, które komunikują się ze sobą, ale mieszkają w oddzielnych domenach. Usługa Web-Layer jest pierwszym punktem kontaktu, a usługa App-Layer jest rzeczywistym wykonawcą. W tej sytuacji udało mi się nieco debugować i odkryłem, że faktycznym wyjątkiem był 405 (metoda niedozwolona) w wywołaniu z warstwy Web do aplikacji. Znalazłem this link po wielu kopaniu, które rozwiązało mój problem.

Podczas korzystania z metody ClientBase<> jako metody komunikacji między usługami, zasadniczo konieczne jest ponowne ustanowienie kontekstu operacji między połączeniami. W przeciwnym razie wszystko staje się POST i jako takie działają tylko POST.

Mam nadzieję, że to pomoże innym i bardzo doceniam pomoc każdej osoby w debugowaniu tego.

Aby zademonstrować, jak to wygląda, co tu jest mój zaktualizowany, implementacja działa serwis internetowy wygląda następująco:

[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Required)] 
[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single, ConcurrencyMode = ConcurrencyMode.Multiple)] 
public class MyApiWebService : ClientBase<IMyApi>, IMyApi 
{ 
    public MyResponseContract GetFileInfo() 
    { 
     MyResponseContract output = null; 

     using(var context = new OperationContext(Channel as IContextChannel)) 
     { 
      output = Channel.GetFileInfo(); 
     } 

     return output; 
    } 
} 
4

Usługa sieci Web .NET WCF jest domyślnie skonfigurowana do wysyłania zakodowanych wiadomości SOAP z tekstem. Oznacza to, że metoda HTTP to POST i są wymagane nagłówki, aby poinformować usługę, jaką metodę wywołać.

Utworzono szybki przykład przy użyciu punktu końcowego usługi, a tutaj jest generowane żądanie od skrzypka, aby porozmawiać z tym punktem końcowym.

POST http://localhost/Utilities/API/GetFileInfo/Service1.svc HTTP/1.1 
Content-Type: text/xml; charset=utf-8 
SOAPAction: "http://tempuri.org/IService1/GetFileInfo" 
Host: localhost:8888 
Content-Length: 136 
Expect: 100-continue 
Connection: Keep-Alive 

<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/"><s:Body><GetFileInfo xmlns="http://tempuri.org/"/></s:Body></s:Envelope> 

Wracając do odpowiedzi

HTTP/1.1 200 OK 
Cache-Control: private 
Content-Length: 398 
Content-Type: text/xml; charset=utf-8 
Server: Microsoft-IIS/8.0 
X-AspNet-Version: 4.0.30319 
X-SourceFiles: =?UTF-8?B?QzpcV29ya1xFSVAgV29ya1xRdWVzdGlvbnNcV0NGR2V0VGVzdFxTZXJ2aWNlMS5zdmM=?= 
X-Powered-By: ASP.NET 
Date: Thu, 21 May 2015 19:47:49 GMT 

<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/"><s:Body><GetFileInfoResponse xmlns="http://tempuri.org/"><GetFileInfoResult xmlns:a="http://schemas.datacontract.org/2004/07/WCFGetTest" xmlns:i="http://www.w3.org/2001/XMLSchema-instance"><a:BoolValue>true</a:BoolValue><a:StringValue>MyResponseContract </a:StringValue></GetFileInfoResult></GetFileInfoResponse></s:Body></s:Envelope> 

dla ciebie Myślę, że coś w swoim SoapUI nie jest prawidłowo ustawiony. Dane pocztowe lub nagłówki.

+0

Ale kiedy po prostu umieszczam URL w przeglądarce, to zwraca ta sama reakcja. –

+0

Jeśli chcesz ujawnić metodę get zwracającą JSON, musisz zmienić powiązanie, aby to zrobić. Spójrz na http: // stackoverflow.com/questions/186631/rest-soap-endpoints-for-a-wcf-service/186695 # 186695 –