为什么遇到 302 响应时 WCF 无法调用 SOAP 服务?

2024-02-21

我编写了一个应用程序,首先调用 WCF 进行登录。我生成了带有服务引用的客户端代码。对于将服务安装到网络本地的客户来说,它工作得很好。然而,也有一个 SaaS 环境,其中这些相同的服务由企业权力控制。 saas环境下,提示登录失败。使用 Fiddler 进行调查,我发现登录的服务调用返回 HTML,特别是列出 .asmx 中所有可用方法的网页。

saas 环境有一个小怪癖,可能会导致这里出现问题,但我不知道如何验证这是否是问题,也不知道如果是问题如何解决。奇怪的是服务器重定向(302)呼叫。

客户端代码:



    client.Endpoint.Address = new EndpointAddress("http://" + settings.MyURL + "/myProduct/webservices/webapi.asmx");
    client.DoLogin(username, password);
  

在重定向之前发送到服务器的原始数据包括 s:Envelope XML 标记。请注意发送到重定向服务器时缺少 s:Envelope XML 标记:



    GET https://www.myurl.com/myProduct/webservices/webapi.asmx https://www.myurl.com/myProduct/webservices/webapi.asmx HTTP/1.1
    Content-Type: text/xml; charset=utf-8
    VsDebuggerCausalityData: uIDPo7TgjY1gCLFLu6UXF8SWAoEAAAAAQxHTAupeAkWz2p2l3jFASiUPHh+L/1xNpTd0YqI2o+wACQAA
    SOAPAction: "http://Interfaces.myProduct.myCompany.com/DoLogin http://Interfaces.myProduct.myCompany.com/DoLogin"
Accept-Encoding: gzip, deflate
    Host: www.gotimeforce2.com
    Connection: Keep-Alive  

我如何让这个愚蠢的事情发挥作用?

Edit:值得注意的是,我使用的是 WCF/svcutil.exe/service-reference 而不是旧的 ASMX/wsdl.exe/web-reference。否则,对于本主题的未来读者来说,Raj 建议的 wsdl 解决方案将是一个很好的解决方案。如果您看到此问题并且正在使用 wsdl 技术,请参阅 Raj 的出色答案。

Edit2:对 WCF 和 302 进行了大量研究后,听起来它们并不能很好地协同工作,而且似乎也没有一种简单的方法可以提供 WCF api 自定义代码来处理这种情况。由于我无法控制服务器,所以我已经吸收了它并重新生成了我的 api 作为网络参考,并且正在使用 Raj 的解决方案。

Edit3:既然已经了解了问题的原因,则更新了标题以更好地反映解决方案。原标题:为什么 WCF 不在重定向中包含 s:Envelope?


好的,所以我对此进行了一些挖掘,并尝试在我这边复制这个问题。我能够复制这个问题并找到解决方案。但是,我不确定这在您的情况下有多适用,因为它取决于与管理负载均衡器的服务器团队的接口。以下是调查结果。

看着http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html您会注意到 HTTP 状态代码 302 和 303 的解释中的以下附录。

302 找到

  Note: RFC 1945 and RFC 2068 specify that the client is not allowed
  to change the method on the redirected request.  However, most
  existing user agent implementations treat 302 as if it were a 303
  response, performing a GET on the Location field-value regardless
  of the original request method. The status codes 303 and 307 have
  been added for servers that wish to make unambiguously clear which
  kind of reaction is expected of the client.

第303章看其他

  Note: Many pre-HTTP/1.1 user agents do not understand the 303
  status. When interoperability with such clients is a concern, the
  302 status code may be used instead, since most user agents react
  to a 302 response as described here for 303.

进一步查看http://en.wikipedia.org/wiki/List_of_HTTP_status_codes您会注意到以下对 HTTP 状态代码 302、303 和 307 的解释。

302 找到:这是行业实践与标准相矛盾的一个例子。 HTTP/1.0 规范 (RFC 1945) 要求客户端执行临时重定向(最初的描述短语是“Moved Temporarily”),但流行的浏览器实现了 302 和 303 See Other 的功能。因此,HTTP/1.1添加了状态码303和307来区分这两种行为。但是,某些 Web 应用程序和框架使用 302 状态代码,就好像它是 303 一样。

303 查看其他(自 HTTP/1.1 起):可以使用 GET 方法在另一个 URI 下找到对请求的响应。当收到对 POST(或 PUT/DELETE)的响应时,应假定服务器已收到数据,并且应使用单独的 GET 消息发出重定向。这是正常客户端/服务器交互的基本流程

307 临时重定向(自 HTTP/1.1 起):在这种情况下,应该使用另一个 URI 重复请求;但是,将来的请求仍应使用原始 URI。与历史上 302 的实现方式相反,重新发出原始请求时不允许更改请求方法。例如,应使用另一个 POST 请求重复一个 POST 请求。

因此,据此,我们能够解释 WCF 调用的行为,该调用在 302 重定向上发送不带 s:Envelope 的 GET 请求。这在客户端无疑会失败。

解决此问题的最简单方法是让服务器在响应中返回 307 临时重定向,而不是 302 Found 状态代码。这就是您需要管理负载均衡器上的重定向规则的服务器团队的帮助。我在本地对此进行了测试,即使使用 307 临时重定向,使用服务引用的服务的客户端代码也可以无缝执行调用。

事实上,你可以使用我上传到 Github 的解决方案来测试这一切Here https://github.com/rexthuhking/WebServiceRedirectHandler。我对此进行了更新,以说明如何利用服务引用而不是 wsdl 生成的代理类来使用 asmx 服务。

但是,如果从 302 Found 更改为 307 临时重定向在您的环境中不可行,那么我建议使用解决方案1 (无论响应中的状态码是 302 还是 307,都不应该有问题)或使用我的原答案这将通过根据配置文件中的设置直接访问正确 URL 的服务来解决此问题。希望这可以帮助!

解决方案1

如果您无权访问生产环境中的配置文件,或者您只是不想在配置文件中使用多个 URL,则可以使用以下方法。包含示例解决方案的 Github 存储库链接点击这里 https://github.com/rexthuhking/WebServiceRedirectHandler

基本上,如果您注意到 wsdl.exe 自动生成的文件,您会注意到服务代理类派生自System.Web.Services.Protocols.SoapHttpClientProtocol。这个类有一个受保护的方法System.Net.WebRequest GetWebRequest(Uri uri)您可以覆盖。在这里你可以添加一个方法来检查 302 临时重定向是否是以下结果的结果HttpWebRequest.GetResponse()方法。如果是这样,您可以将 Url 设置为返回的新 UrlLocation响应的标头如下。

this.Url = new Uri(uri, response.Headers["Location"]).ToString();

因此,创建一个名为 SoapHttpClientProtocolWithRedirect 的类,如下所示。

public class SoapHttpClientProtocolWithRedirect :
    System.Web.Services.Protocols.SoapHttpClientProtocol
{
    protected override System.Net.WebRequest GetWebRequest(Uri uri)
    {
        if (!_redirectFixed)
        {
            FixRedirect(new Uri(this.Url));
            _redirectFixed = true;

            return base.GetWebRequest(new Uri(this.Url));
        }

        return base.GetWebRequest(uri);
    }

    private bool _redirectFixed = false;
    private void FixRedirect(Uri uri)
    {
        var request = (HttpWebRequest)WebRequest.Create(uri);
        request.CookieContainer = new CookieContainer();
        request.AllowAutoRedirect = false;
        var response = (HttpWebResponse)request.GetResponse();

        switch (response.StatusCode)
        {
            case HttpStatusCode.Redirect:
            case HttpStatusCode.TemporaryRedirect:
            case HttpStatusCode.MovedPermanently:
                this.Url = new Uri(uri, response.Headers["Location"]).ToString();
                break;
        }
    }
}

现在的部分说明了使用 wsdl.exe 手动生成的代理类而不是服务引用的优点。在手动创建的代理类中。修改类声明

public partial class WebApiProxy : System.Web.Services.Protocols.SoapHttpClientProtocol

to

public partial class WebApiProxy : SoapHttpClientProtocolWithRedirect

现在按如下方式调用 DoLogin 方法。

var apiClient = new WebApiProxy(GetServiceUrl());
//TODO: Add any required headers etc.
apiClient.DoLogin(username,password);

您会注意到 SoapHttpClientProtocolWithRedirect 类中的代码可以顺利处理 302 重定向。

另一个优点是,通过这样做,您不必担心其他开发人员会刷新服务引用并丢失您对代理类所做的更改,因为您手动生成了代理类。希望这可以帮助。

原答案

为什么不在配置文件中包含生产/本地服务的完整 URL?这样您就可以在适当的位置使用适当的 url 发起呼叫。

另外,我不会在任何用于生产的代码中使用服务引用。在没有服务引用的情况下使用 asmx 服务的一种方法是使用 wsdl.exe 工具生成 WebApiProxy.cs 文件。现在,您只需将 WebApiProxy.cs 文件包含在项目中并实例化,如下所示。

var apiClient = new WebApiProxy(GetServiceUrl());
//TODO: Add any required headers etc.
apiClient.DoLogin(username,password);

这是 GetServiceUrl() 方法。使用配置存储库进一步解耦并提高可测试性。

private string GetServiceUrl()
    {
        try
        {
            return
            _configurationRepository.AppSettings[
                _configurationRepository.AppSettings["WebApiInstanceToUse"]];
        }
        catch (NullReferenceException ex)
        {
            //TODO: Log error
            return string.Empty;
        }
    }

然后您的配置文件可以在该部分包含以下信息。

<add key="StagingWebApiInstance" value="http://mystagingserver/myProduct/webservices/webapi.asmx "/>
<add key="ProductionWebApiInstance" value="https://www.myurl.com/myProduct/webservices/webapi.asmx"/>
<!-- Identify which WebApi.asmx instance to Use-->
<add key="WebApiInstanceToUse" value="ProductionWebApiInstance"/>

另外,我会避免使用 + 重载来连接字符串。当执行一次时,它不会对性能产生太大影响,但如果在整个代码中有很多这样的串联,与使用 StringBuilder 相比,它将导致执行时间的巨大差异。查看http://msdn.microsoft.com/en-us/library/ms228504.aspx有关为什么使用 StringBuilder 可以提高性能的更多信息。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

为什么遇到 302 响应时 WCF 无法调用 SOAP 服务? 的相关文章

  • 删除文件的最后 10 个字符

    我想删除文件的最后 10 个字符 说一个字符串 hello i am a c learner 是文件内的数据 我只是希望该文件是 hello i am a 文件的最后 10 个字符 即字符串 c learner 应在文件内消除 解决方案 将
  • 机器Epsilon精度差异

    我正在尝试计算 C 中双精度数和浮点数的机器 epsilon 值 作为学校作业的一部分 我在 Windows 7 64 位中使用 Cygwin 代码如下 include
  • free 和 malloc 在 C 中如何工作?

    我试图弄清楚如果我尝试 从中间 释放指针会发生什么 例如 看下面的代码 char ptr char malloc 10 sizeof char for char i 0 i lt 10 i ptr i i 10 ptr ptr ptr pt
  • 传递给函数时多维数组的指针类型是什么? [复制]

    这个问题在这里已经有答案了 我在大学课堂上学习了 C 语言和指针 除了多维数组和指针之间的相似性之外 我认为我已经很好地掌握了这个概念 我认为由于所有数组 甚至多维 都存储在连续内存中 因此您可以安全地将其转换为int 假设给定的数组是in
  • 如何在 C++ 中标记字符串?

    Java有一个方便的分割方法 String str The quick brown fox String results str split 在 C 中是否有一种简单的方法可以做到这一点 The 增强分词器 http www boost o
  • IIS 7.5 托管的 WCF 服务仅针对大型请求抛出 EndpointNotFoundException 和 404

    我有一个 WCF REST 服务托管在 IIS 7 5 Windows 2008 R2 上 该服务按预期工作 除非客户端尝试发送大于 25 MB 的消息 具体来说 当发送大小约为 25 MB 的消息时 服务会正确接收并处理消息 而当发送大小
  • 如何使从 C# 调用的 C(P/invoke)代码“线程安全”

    我有一些简单的 C 代码 它使用单个全局变量 显然这不是线程安全的 所以当我使用 P invoke 从 C 中的多个线程调用它时 事情就搞砸了 如何为每个线程单独导入此函数 或使其线程安全 我尝试声明变量 declspec thread 但
  • 在 Unity 中实现 Fur with Shells 技术

    我正在尝试在 Unity 中实现皮毛贝壳技术 http developer download nvidia com SDK 10 5 direct3d Source Fur doc FurShellsAndFins pdf Fins 技术被
  • 两个静态变量同名(两个不同的文件),并在任何其他文件中 extern 其中一个

    在一个文件中将变量声明为 static 并在另一个文件中进行 extern 声明 我认为这会在链接时出现错误 因为 extern 变量不会在任何对象中看到 因为在其他文件中声明的变量带有限定符 static 但不知何故 链接器 瑞萨 没有显
  • 结构体的内存大小不同?

    为什么第一种情况不是12 测试环境 最新版本的 gcc 和 clang 64 位 Linux struct desc int parts int nr sizeof desc Output 16 struct desc int parts
  • 为什么这个字符串用AesCryptoServiceProvider第二次解密时不相等?

    我在 C VS2012 NET 4 5 中的文本加密和解密方面遇到问题 具体来说 当我加密并随后解密字符串时 输出与输入不同 然而 奇怪的是 如果我复制加密的输出并将其硬编码为字符串文字 解密就会起作用 以下代码示例说明了该问题 我究竟做错
  • 为什么 C# 2.0 之后没有 ISO 或 ECMA 标准化?

    我已经开始学习 C 并正在寻找标准规范 但发现大于 2 0 的 C 版本并未由 ISO 或 ECMA 标准化 或者是我从 Wikipedia 收集到的 这有什么原因吗 因为编写 审查 验证 发布 处理反馈 修订 重新发布等复杂的规范文档需要
  • 实例化类时重写虚拟方法

    我有一个带有一些虚函数的类 让我们假设这是其中之一 public class AClassWhatever protected virtual string DoAThingToAString string inputString retu
  • C# 动态/expando 对象的深度/嵌套/递归合并

    我需要在 C 中 合并 2 个动态对象 我在 stackexchange 上找到的所有内容仅涵盖非递归合并 但我正在寻找能够进行递归或深度合并的东西 非常类似于jQuery 的 extend obj1 obj2 http api jquer
  • 如何实例化 ODataQueryOptions

    我有一个工作 简化 ODataController用下面的方法 public class MyTypeController ODataController HttpGet EnableQuery ODataRoute myTypes pub
  • 有没有办法让 doxygen 自动处理未记录的 C 代码?

    通常它会忽略未记录的 C 文件 但我想测试 Callgraph 功能 例如 您知道在不更改 C 文件的情况下解决此问题的方法吗 设置变量EXTRACT ALL YES在你的 Doxyfile 中
  • 相当于Linux中的导入库

    在 Windows C 中 当您想要链接 DLL 时 您必须提供导入库 但是在 GNU 构建系统中 当您想要链接 so 文件 相当于 dll 时 您就不需要链接 为什么是这样 是否有等效的 Windows 导入库 注意 我不会谈论在 Win
  • C# 中的 IPC 机制 - 用法和最佳实践

    不久前我在 Win32 代码中使用了 IPC 临界区 事件和信号量 NET环境下场景如何 是否有任何教程解释所有可用选项以及何时使用以及为什么 微软最近在IPC方面的东西是Windows 通信基础 http en wikipedia org
  • C# 使用“?” if else 语句设置值这叫什么

    嘿 我刚刚看到以下声明 return name null name NA 我只是想知道这在 NET 中叫什么 是吗 代表即然后执行此操作 这是一个俗称的 条件运算符 三元运算符 http en wikipedia org wiki Tern
  • 指针和内存范围

    我已经用 C 语言编程有一段时间了 但对 C 语言还是很陌生 有时我对 C 处理内存的方式感到困惑 考虑以下有效的 C 代码片段 const char string void where is this pointer variable l

随机推荐

  • F#:实现函数名与关键字begin相同的接口

    我正在尝试实现 IVector 接口 它是 Microsoft VisualC StlClr 命名空间的一部分 它有一个成员函数begin 如果我尝试实现该接口 那么它会抱怨 对象表达式中出现意外的关键字 开始 这是因为 begin 是一个
  • glibc中的CSU代表什么?

    我正在读一本article http dbp consulting com tutorials debugging linuxProgramStartup html在C启动时 它指的是函数 libc csu init 谁能告诉我 CSU 代
  • 在打字稿中应该定义什么类型的超时

    我正在尝试在打字稿中编写一个去抖函数 但不确定要设置分配给什么类型的变量setTimeout 我的代码如下所示 function debounced func gt void wait number what type should tim
  • Ajax 操作 URL 不起作用 + Symfony2

    我想使用 jquery 自动完成功能进行 ajax 调用 如下所示 register player team autocomplete source function request response ajax url path volle
  • VIM:全局匹配行,删除此行和以下2行

    以下是我的想法 g All Claims t 0 3d 但这不起作用 在这种模式下乘以一个动作似乎是无效的语法 我最终得到了以下序列 qq All Claims t 0 3dd q 10000 q 这种宏观组合效果很好 我只是好奇是否有一些
  • Webpack:将 html 部分包含在另一个部分中?

    有没有办法使用 webpack 将 html 部分包含在另一个部分中 我正在使用 html loader 来执行此操作 索引 html 但是当我尝试在 header html 中包含另一个部分时 它无法渲染它 这是行不通的 header h
  • 在 GEdit 中创建您自己的语法突出显示?

    如何将 关键字 添加到 GEdit 关键字列表中 我基本上想让 printf 函数看起来像一个关键字 printf Hello World n GEdit 使用Gtk源视图 http projects gnome org gtksource
  • 基于 XMPP 协议的 Google Cloud Messaging(使用 PHP 和 XMPPHP 的服务器)。它是如何工作的?

    也许你已经听说过它 它是在一个月前的 Google IO 上宣布的 Google Cloud Messaging 仅位于下游 服务器 gt 电话 但现在通过增强的 CCS 云连接服务器 您可以通过持久 TCP 连接向上游发送消息 这要归功于
  • 标准定义的setjmp备注

    ISO IEC 9899 1999 7 13 1 1 setjmp 宏 环境限制 4 应出现 setjmp 宏的调用 仅在以下情况之一 整个控制 选择或迭代语句的表达式 a 的一个操作数 关系运算符或相等运算符 另一个操作数为整数 常量表达
  • 由于异步图像加载,图像的宽度和高度为零

    我有一个很长的base64输入我得到的字符串 我想将其设置为src图像的 img attr src base64data console log height img height console log width img height
  • Pandas 按每列分组并为每组添加新列

    我有一个像这样的数据框 lvl1 l1A l1A l1B l1C l1D lvl2 l2A l2A l2A l26 l27 wgt 2 3 15 05 3 lvls lvl1 lvl2 df pd DataFrame wgt lvls re
  • 多行字符串作为序列的一部分

    我不知道如何使用多行字符串作为 yaml 序列的一部分 foo bar bar2 gt super duper long string that I would like to have on multiple lines Another
  • Sql -WITH ... AS 的替代方案

    有没有一个高效的这个例子的替代SQL 我不想使用WITH AS 这是主要标准 WITH TEMP TABLE AS SELECT status COUNT 1 as total FROM XYZ GROUP BY status SELECT
  • Elastic beanstalk ebextensions/config:找不到包“libffi”

    这是我的配置 我在 ebextensions 中只有 2 个配置 01run config 和 02do config ebextensions 01run config packages yum python27 devel postgr
  • 无法运行 scons 并出现导入错误

    我已经安装了 scons 2 3 2 并安装了 python 2 4 当我运行 scons 时 我看到以下错误 scons Import failed Unable to find SCons files in usr bin engine
  • 对象数组的 AJV 模式验证

    我正在尝试使用 AJV 模式验证来验证对象数组 下面是示例代码 var Ajv require ajv var schemaValidator Ajv var innerSchema type object properties c typ
  • Javascript 非法令牌错误

    如果这是一个简单的问题 请原谅我 但我似乎无法找到这段代码的原因 function create content c var html div c div if c links var ul ul li a href http www my
  • Iframe SandBox 阻止嵌入对象

    为什么有例子Example http www ufilme ro index cereri 0 11为什么当我使用 沙箱我看不到播放器 我想使用沙箱只是为了阻止弹出窗口 但看起来如果我使用它我看不到播放器 有没有allow objects
  • 如何通过脚本从sql server代理获取失败的作业?

    我想获取 sql server 代理无法通过 sql 脚本启动或运行的失败作业 我创建了一个视图来获取sql server中失败的作业 CREATE VIEW dbo View Failed Jobs AS SELECT Job insta
  • 为什么遇到 302 响应时 WCF 无法调用 SOAP 服务?

    我编写了一个应用程序 首先调用 WCF 进行登录 我生成了带有服务引用的客户端代码 对于将服务安装到网络本地的客户来说 它工作得很好 然而 也有一个 SaaS 环境 其中这些相同的服务由企业权力控制 saas环境下 提示登录失败 使用 Fi