即使指定了 WebGet 属性,WCF 代理也使用 Post(仅当从另一个 WCF 服务调用时) - 导致 405 错误

发布于 2024-09-24 08:44:31 字数 2487 浏览 0 评论 0原文

我有一个 Restful WCF 服务位于另一台服务器上,配置了 WebGet 属性来响应 HTTP Get 方法。我知道该服务工作正常,因为我可以直接通过浏览器调用该服务,并使用 Fiddler 手动执行 Get 并收到正确的响应。

我的本地计算机上有一个 Asp.NET 项目,它使用以下代码调用此服务:

代理接口 'IProductService':

using System.ServiceModel;
using System.ServiceModel.Web;

namespace Hugo.Infrastructure.Services.Products
{
    [ServiceContract]
    [XmlSerializerFormat]
    public interface IProductService
    {
        [OperationContract(Name = "GetProductById")]
        [WebGet(UriTemplate = "Products/Titles/{id}",
            ResponseFormat = WebMessageFormat.Xml,
            RequestFormat = WebMessageFormat.Xml,
            BodyStyle = WebMessageBodyStyle.Bare)]
        TitleDto GetTitleById(string id);
    }
}

实现 'ProductService':

using System.ServiceModel;

namespace Hugo.Infrastructure.Services.Products
{
    public class ProductService : ClientBase<IProductService>, IProductService
    {
        public TitleDto GetTitleById(string id)
        {
            return Channel.GetTitleById(id);
        }
    }
}

相关 Web.config 部分:

<system.serviceModel>
    <serviceHostingEnvironment aspNetCompatibilityEnabled="true">
        <baseAddressPrefixFilters>
        </baseAddressPrefixFilters>      
    </serviceHostingEnvironment>
    ...
    <client>
        <endpoint address="http://server/directory/product.svc" bindingConfiguration="ProductServiceBinding" binding="webHttpBinding" behaviorConfiguration="productService" contract="Project.Infrastructure.Services.Products.IProductService" name="ProductServiceRest" />
    </client>
    <behaviors>
        ...
        <endpointBehaviors>
            <behavior name="productService">
                <webHttp />
            </behavior>
            ...
        </endpointBehaviors>
    </behaviors>
</system.serviceModel>

当我们从其中的页面调用该方法时,效果很好但是,当我们从同一项目的 WCF 服务中调用它时,它会在该行 return Channel.GetTitleById(id); 上出错。我们收到的错误是 HTTP 405“方法不允许”错误。当我们查看远程服务器上的 IIS 日志时,我们发现,当从页面发起方法调用时,ProductService 代理正在发出 HTTP GET 请求,但当从 WCF 服务调用该方法时,它正在发出 HTTP POST 请求。服务上未配置 POST 方法,因此出现 405 错误。

即使页面和服务位于同一文件夹和命名空间中,我们仍然会从服务收到相同的错误。如果我们使用经典的 asmx Soap 服务,则会进行 GET 调用,并且服务会正确执行和响应。如果我们使用 System.Net.WebRequest 对象手动从 WCF 服务获取,则服务调用会成功。

底线是,当在另一个 WCF Rest 服务中使用时,WCF 客户端代理尝试执行 POST 而不是 GET,但在页面或几乎其他任何地方使用时可以正常工作。

请帮忙!

I have a Restful WCF service sitting on another server configured with the WebGet attribute to respond to the HTTP Get method. I know the service works correctly because I can call the service directly through the browser and manually do a Get with Fiddler and receive a correct response.

I have an Asp.NET project on my local machine that is calling this service with the following code:

Proxy Interface 'IProductService':

using System.ServiceModel;
using System.ServiceModel.Web;

namespace Hugo.Infrastructure.Services.Products
{
    [ServiceContract]
    [XmlSerializerFormat]
    public interface IProductService
    {
        [OperationContract(Name = "GetProductById")]
        [WebGet(UriTemplate = "Products/Titles/{id}",
            ResponseFormat = WebMessageFormat.Xml,
            RequestFormat = WebMessageFormat.Xml,
            BodyStyle = WebMessageBodyStyle.Bare)]
        TitleDto GetTitleById(string id);
    }
}

Implementation 'ProductService':

using System.ServiceModel;

namespace Hugo.Infrastructure.Services.Products
{
    public class ProductService : ClientBase<IProductService>, IProductService
    {
        public TitleDto GetTitleById(string id)
        {
            return Channel.GetTitleById(id);
        }
    }
}

Related Web.config section:

<system.serviceModel>
    <serviceHostingEnvironment aspNetCompatibilityEnabled="true">
        <baseAddressPrefixFilters>
        </baseAddressPrefixFilters>      
    </serviceHostingEnvironment>
    ...
    <client>
        <endpoint address="http://server/directory/product.svc" bindingConfiguration="ProductServiceBinding" binding="webHttpBinding" behaviorConfiguration="productService" contract="Project.Infrastructure.Services.Products.IProductService" name="ProductServiceRest" />
    </client>
    <behaviors>
        ...
        <endpointBehaviors>
            <behavior name="productService">
                <webHttp />
            </behavior>
            ...
        </endpointBehaviors>
    </behaviors>
</system.serviceModel>

This works fine when we call the method from a page within the project, however it errors out on this line return Channel.GetTitleById(id); when we call it from within a WCF service from the same project. The error we receive is an HTTP 405 'Method not allowed' error. When we look at the IIS logs on the remote server we see that the ProductService proxy is making an HTTP GET request when the method call is initiated from the page but it is making an HTTP POST request when the method is called from the WCF service. The POST method is not configured on the service, thus the 405 error.

Even when the page and the service are in the same folder and namespace we still receive the same error from the service. If we use a classic asmx soap service instead then a GET call is made and the service executes and responds correctly. If we manually do a get from the WCF service using the System.Net.WebRequest object, the service call succeeds.

Bottom line, the WCF client proxy tries to do a POST instead of a GET when used from within another WCF Rest service but works correctly when used from a page or pretty much anywhere else.

Help please!

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

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

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文