调用 WCF 服务操作时出现 HTTP 400 错误请求?

发布于 2024-11-06 17:57:21 字数 4128 浏览 4 评论 0原文

当我调用 http://localhost/TestService.svc/GetColors 时,我收到 Http (400) Bad要求。当我在 fiddler 中运行它时,我也收到错误请求。当我通过 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 的 Validate 方法实现自定义验证,但是当我通过 wcf 客户端调用类似 GetColors 之类的方法时,它不会调用 Validate 方法。我可以让它调用验证的唯一方法是直接在 GetColors 中调用 Validate(user,pass)。我认为如果你在 web.config 中正确设置了它,每次服务调用都会自动调用它。

When I call http://localhost/TestService.svc/GetColors, I get a Http (400) Bad Request. When I run this in fiddler, I also get Bad Request. When I invoke the service through the wcf test client, it works fine though. What could cause this?

Service contract:

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

Implementation of 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;
    }
}

Here is my 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>

When I call it, I just open up a any browser and put the url http://localhost/TestService.svc/GetColors. If I do it through the dev environment, I see the Http 400 bad request. If I do it through IIS, I just see a blank page.

Here is the InnerException:

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

Another question regarding my CustomUserNameValidation:

I am implementing Custom Validation through the Validate Method of UserNamePasswordValidator, but when I call something like GetColors through the wcf client, it does not invoke the Validate method. The only way I can get it to Invoke validate is if I call Validate(user,pass) directly in GetColors. I thought it woulld be called automatically for every service call if you have it setup correctly in web.config.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

虫児飞 2024-11-13 17:57:21

您的服务契约和服务实现似乎不匹配......

服务契约定义了从GetColors()返回的单个字符串

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

但是实现返回一个List 相反:

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

您是否有可能更改服务实现,并且忘记更新服务合同?

另外:由于这是一个带有 wsHttpBinding 的 SOAP 服务,您不能仅通过浏览其地址来从浏览器调用该方法 - 您需要使用 WCF 测试客户端(正如你所说,这有效)。您也不能只从 Fiddler 调用它 - 您必须手动创建包含标头和正文等的整个 SOAP 信封 - 这根本不是一件容易的任务。

您可以尝试访问 http://localhost/TestService.svc?wsdl 检查是否能获取该服务的正确 WSDL。

Your service contract and service implementation don't seem to match....

The service contract defines a single string to be returned from GetColors():

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

But the implementation returns a List<Color> instead:

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

Is there any chance you changed your service implementation, and forgot to update the service contract??

Also: since this is a SOAP service with a wsHttpBinding, you cannot just call the method from a browser by browsing to its address - you need to use the WCF Test Client (which works, as you say). Nor can you just call it from Fiddler, either - you would have to manually create the entire SOAP envelope with header and body and all - not an easy task at all.

What you can try is to go to http://localhost/TestService.svc?wsdl to check whether you'll get back the proper WSDL for the service.

汐鸠 2024-11-13 17:57:21

很多事情都可能导致这种情况。我建议您首先启用 WCF 跟踪,它通常非常有用,因为它为您提供实际情况的服务器端输出。以下链接应该会有所帮助:如何启用 WCF 跟踪

编辑:WCF 需要注意的一点是:与自动生成的 ole' ASMX Web 服务不同,它不允许您使用标准浏览到基地址浏览器。您可以浏览到元数据地址(mex 地址),但不能浏览到根目录。这只是设计使然(我相信 HTTP 方法不受支持)。

Many things could cause this. I suggest you first enable WCF Tracing, it's usually very helpful as it gives you the server side output of what's really going on. Here is a link that should help: How to enable WCF tracing

EDIT: One little thing to note with WCF: unlike auto generated ole' ASMX web service it does not allow you to browse to the base address with a standard browser. You can browse to the Metadata address (the mex one), but not to the root. This is just by design (the HTTP method is not supported I believe).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文