Неверный запрос HTTP 400 при вызове операции службы WCF?

Когда я вызываю http://localhost/TestService.svc/GetColors, я получаю Http (400) Bad Запрос. Когда я запускаю это в скрипте, я также получаю неверный запрос. Когда я вызываю сервис через тестовый клиент 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:

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


person Xaisoft    schedule 13.05.2011    source источник
comment
@marc_s, обновлю свой пост.   -  person Xaisoft    schedule 13.05.2011


Ответы (2)


Ваш контракт на обслуживание и реализация услуги не совпадают ....

Контракт службы определяет один 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 для службы.

person marc_s    schedule 13.05.2011
comment
Извините, marc_s, я просто забыл отредактировать его здесь. Мой текущий код - Список ‹Color› GetColors (); в моем интерфейсе. - person Xaisoft; 13.05.2011
comment
marc_s, спасибо за помощь. Я получаю правильный файл wsdl. Есть ли у вас какие-либо представления о проблеме с валидатором пароля для имени пользователя? - person Xaisoft; 13.05.2011
comment
Используйте SoapUI для тестирования, он создает для вас пустые запросы, затем вы заполняете параметры и отправляете их - person SparK; 11.02.2014

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

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

person Simon Mourier    schedule 13.05.2011
comment
хорошо, я включил трассировку. Как мне теперь извлечь из этого что-то значимое? - person Xaisoft; 13.05.2011
comment
Вам необходимо использовать инструмент Service Trace Viewer Tool: msdn.microsoft.com/en- us / library / ms732023.aspx - person Simon Mourier; 13.05.2011
comment
Я нашел это, но, похоже, не вижу никаких проблем. Я не вижу значков ошибок. Есть ли что-нибудь, на что мне следует обратить внимание? - person Xaisoft; 13.05.2011
comment
@xaisoft - я обновил свой ответ. Я думаю, вы пытаетесь просмотреть базовый адрес. Вы просто не можете этого сделать. - person Simon Mourier; 13.05.2011
comment
Саймон, ты прав. Я пытаюсь перейти к базовому адресу \ GetColors. Означает ли это, что на самом деле все работает так, как должно работать, и эта ошибка на самом деле является ожидаемой, когда я пытаюсь вызвать операцию (GetColors) через URL-адрес браузера. - person Xaisoft; 13.05.2011
comment
У меня есть еще один вопрос, который вы, возможно, знаете, так как я опубликовал свой файл web.config. - person Xaisoft; 13.05.2011