HTTP 400 Bad Request при вызове операции сервиса WCF? - PullRequest
6 голосов
/ 13 мая 2011

Когда я звоню http://localhost/TestService.svc/GetColors,, я получаю Http (400) Bad Request. Когда я запускаю это в fiddler, я также получаю Bad Request. Когда я вызываю сервис через тестовый клиент wcf, он работает нормально. Что может вызвать это?

Договор на обслуживание:

[ServiceContract]
public interface ITestService
{
    [OperationContract]
    string GetColors();
}

Внедрение ITestService:

[ServiceBehavior(InstanceContextMode=InstanceContextMode.Single)]
public class TestService : ITestService
{
    public List<Color> GetColors()
    {
        List<Color> colors= new List<Color>();

        colors.Add(new Color { Name = "Red", Code = "123" });
        colors.Add(new Color { Name = "Blue", Code = "323" });
        colors.Add(new Color { Name = "Green", Code = "3394" });

       return colors;
    }
}

Вот мой web.config:

<?xml version="1.0"?>
<configuration>
   <system.web>
       <compilation debug="true" targetFramework="4.0"/>
   </system.web>
   <system.serviceModel>
      <bindings>
         <wsHttpBinding>
            <binding name="CustomAuthentication">
               <security mode="Message">
                  <message clientCredentialType="UserName"/>
               </security>
            </binding>
         </wsHttpBinding>
      </bindings>
      <serviceHostingEnvironment multipleSiteBindingsEnabled="true"/>
      <services>
          <service name="TestService.TestService"
                behaviorConfiguration="CustomValidator" >
             <endpoint 
                 address="" 
                 binding="wsHttpBinding" 
                 bindingConfiguration="CustomAuthentication"
                 contract="TestService.ITestService">
                 <identity>
                    <dns value="localhost" />
                 </identity>
             </endpoint>
             <endpoint 
                 address="mex" 
                 binding="mexHttpBinding" 
                 contract="IMetadataExchange" />
             <host>
                 <baseAddresses>
                     <add baseAddress="http://localhost/TestService/" />
                 </baseAddresses>
             </host>
          </service>
      </services>
      <behaviors>
          <serviceBehaviors>
             <behavior name="CustomValidator">
                <serviceCredentials>
                   <userNameAuthentication userNamePasswordValidationMode="Custom"
                                customUserNamePasswordValidatorType="TestService.CustomUserNameValidator, TestService"/>
                   <serviceCertificate findValue="Test" storeLocation="LocalMachine" 
                         storeName="My" x509FindType="FindBySubjectName"/>
                </serviceCredentials>
                <serviceMetadata httpGetEnabled="True"/>
             </behavior>
             <behavior>
                <serviceMetadata httpGetEnabled="True"/>
                <serviceDebug includeExceptionDetailInFaults="False"/>
             </behavior>
         </serviceBehaviors>
      </behaviors>
   </system.serviceModel>
   <system.webServer>
       <modules runAllManagedModulesForAllRequests="true"/>
   </system.webServer>
</configuration>

Когда я его вызываю, я просто открываю любой браузер и вставляю URL http://localhost/TestService.svc/GetColors. Если я делаю это через среду разработки, я вижу неправильный запрос Http 400. Если я делаю это через IIS, я просто вижу пустую страницу.

Вот InnerException:

<ExceptionString>System.Xml.XmlException: The body of the message cannot be read  
because it is empty.</ExceptionString>

Еще один вопрос относительно моего CustomUserNameValidation:

Я реализую пользовательскую проверку с помощью метода Validate метода UserNamePasswordValidator, но когда я вызываю что-то вроде GetColors через клиент wcf, он не вызывает метод Validate. Единственный способ передать его в Invoke validate - это вызвать Validate (user, pass) непосредственно в GetColors. Я думал, что он будет вызываться автоматически при каждом вызове службы, если вы правильно настроили его в web.config.

Ответы [ 2 ]

5 голосов
/ 13 мая 2011

Ваш сервисный контракт и реализация сервиса, похоже, не совпадают ....

Сервисный контракт определяет один string, который будет возвращен из GetColors():

[ServiceContract]
public interface ITestService
{
    [OperationContract]
    string GetColors();
}

Но реализация возвращает List<Color> вместо:

[ServiceBehavior(InstanceContextMode=InstanceContextMode.Single)]
public class TestService : ITestService
{
    public List<Color> GetColors()
    {

Есть ли шанс, что вы изменили реализацию своего сервиса и забыли обновить контракт на обслуживание ??

Также: поскольку это SOAP-сервис с wsHttpBinding, вы не можете просто вызвать метод из браузера, перейдя по его адресу - вам нужно использовать тестовый клиент WCF (который работает, как ты говоришь). Вы также не можете просто вызвать его из Fiddler - вам придется вручную создать весь конверт SOAP с заголовком и телом и все - совсем не простая задача.

Что вы можете попробовать, так это перейти на http://localhost/TestService.svc?wsdl, чтобы проверить, вернете ли вы правильный WSDL для службы.

0 голосов
/ 13 мая 2011

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

РЕДАКТИРОВАТЬ : В WCF нужно отметить одну небольшую вещь: в отличие от автоматически сгенерированного веб-сервиса ole 'ASMX, он не позволяет просматривать по базовому адресу в стандартном браузере. Вы можете перейти к адресу метаданных (mex), но не к корню. Это просто дизайн (я думаю, что метод HTTP не поддерживается).

...