【问题标题】:Invoke of webservice fails with HTTP status 400 Bad Request调用 Web 服务失败,HTTP 状态为 400 错误请求
【发布时间】:2011-03-26 12:49:56
【问题描述】:

我的网络应用程序调用网络服务失败:

“/zVersion2a”应用程序中的服务器错误。 请求失败,HTTP 状态 400:错误请求。

这是一个指向网络服务本身的链接(有效):

http://www.zipeee.com/Zipeeewebservice/

这是一个在第一个页面加载时调用 WS 的 [生产] Web 应用程序的链接:

http://www.zipeee.com/Zipeee/

以下是 [newVersion] Web 应用程序的链接,该应用程序调用相同的 WS 失败:

http://www.zipeee.com/zVersion2/

这里是调用页面中的源代码:

Imports System.Data
Partial Class frmZipeee
Inherits System.Web.UI.Page
Public wsZipeee As New ProxyZipeeeService.WSZipeee.Zipeee
Dim dsStandardMsg As DataSet
Dim dtStandardMsg As DataTable
Dim dsRandomMsg As DataSet
Dim dtRandomMsg As DataTable
Private Sub Page_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
    If Not Page.IsPostBack Then
        LoadMessage()
    End If
End Sub
Private Sub LoadMessage()
    Dim iCnt As Integer
    Dim iValue As Integer

    dsStandardMsg = Nothing
    dsStandardMsg = wsZipeee.GetMessageByType(BizConstants.MsgType.Standard)
    iCnt = dsStandardMsg.Tables(0).Rows.Count
        If iCnt = 0 Then
            Me.btnEnter.Text = "Click Here to Enter."
        Else
            Me.btnEnter.Text = dsStandardMsg.Tables(0).Rows(0).Item("MessageContent")
        End If
    dsStandardMsg.Dispose()
End Sub
End Class

以下是 代理 中 Reference.vb 的代码:

<System.Web.Services.Protocols.SoapDocumentMethodAttribute("http://tempuri.org/ZipeeeWebService/Zipeee/Get Message By Type", RequestElementName:="Get Message By Type", RequestNamespace:="http://tempuri.org/ZipeeeWebService/Zipeee", ResponseElementName:="Get Message By TypeResponse", ResponseNamespace:="http://tempuri.org/ZipeeeWebService/Zipeee", Use:=System.Web.Services.Description.SoapBindingUse.Literal, ParameterStyle:=System.Web.Services.Protocols.SoapParameterStyle.Wrapped)>  _
    Public Function GetMessageByType(ByVal iMsgType As Integer) As <System.Xml.Serialization.XmlElementAttribute("Get Message By TypeResult")> System.Data.DataSet
        Dim results() As Object = Me.Invoke("GetMessageByType", New Object() {iMsgType})
        Return CType(results(0),System.Data.DataSet)
    End Function

最后,这是webservice中的代码:

   <WebMethod(MessageName:="Get Message By Type")> _
           Public Function GetMessageByType(ByVal iMsgType As Integer) As DataSet
    Try
        'create a connection...
        con = New SqlConnection(sConnZipeee)
        con.Open()
        command = New SqlCommand("spGetMessageByType", con)
        command.CommandType = CommandType.StoredProcedure
        AppendParm(command, "@MessageType", SqlDbType.Int, iMsgType)
        Dim adp As SqlDataAdapter = New SqlDataAdapter(command)
        Dim ds As New DataSet
        adp.Fill(ds, "TableMsg")
        adp.Dispose()
        command.Dispose()
        con.Close()
        Return ds
    Catch ex As SqlException
     ...etc.                'As I read the trace output (below) we never got here nor to SQL

在这个运行 IIS 6.0 Windows 2003 的生产网络服务器上,默认网站中有 3 个虚拟目录(Zipeee、zVersion2、ZipeeeWebService)。

每个虚拟目录都指向网络服务器 C 盘上的一个单独的物理目录。生产 Zipeeee 和 newVersion zVersion2 都使用名为 ProxyZipeeeService.dll 的代理类。我在发布主要项目Zipeee 及其所需的网络服务时非常小心。例如,在使用 Visual Studio2008 的开发服务器上,我构建并测试了所有 5 个项目(webservice1、webservice2、primarywebapp(即 zipeee)、proxyclassforWS1、proxyclassforWS2)。所有这些 DLL 的最新版本都标有选择为 1.6 的程序集版本。它们都在我的开发机器上工作,我将 WS1、WS2 和 zipeee 发布到临时服务器(IIS 6.0),它们也都在那里工作。然后我发布到托管上述 URL 的公共服务器。新版本的 Web 应用程序位于 c 盘上的单独文件夹中,并由 vDir zVersion2 指向。它应该可以工作,但由于此 WS 错误,甚至无法呈现第一页。

我追踪了 zVersion2 的失败(它在页面加载事件中调用 webmethod GetMessageByType 并立即失败)。这是(不是很长,但是这里的格式有点乱):

System.Web.Services.Asmx 信息:0:调用 XmlSerializer [创建 XmlSerializer] 方法:System.Xml.Serialization.XmlSerializer#1669721556::FromMappings(System.Xml.Serialization.XmlMapping[]#40041277=[356], ProxyZipeeeService.WSZipeee.Zipeee#50200644=ProxyZipeeeService.WSZipeee.Zipeee) 调用方:System.Web.Services.Protocols.SoapClientType#24827179::.ctor(ProxyZipeeeService.WSZipeee.Zipeee#50200644=ProxyZipeeeService.WSZipeee.Zipeee) 进程 ID=1456 逻辑操作栈= 线程 ID=1 日期时间=2010-08-06T01:58:45.6541439Z 时间戳=47298006836 System.Web.Services.Asmx 信息:0:从 XmlSerializer 返回 [创建 XmlSerializer] 调用方:System.Web.Services.Protocols.SoapClientType#24827179::.ctor(ProxyZipeeeService.WSZipeee.Zipeee#50200644=ProxyZipeeeService.WSZipeee.Zipeee) 进程 ID=1456 逻辑操作栈= 线程 ID=1 日期时间=2010-08-06T01:58:45.7791255Z 时间戳=47298376293 System.Web.Services.Asmx 信息:0:调用 XmlSerializer [创建 XmlSerializer] 方法:System.Xml.Serialization.XmlSerializer#1669721556::FromMappings(System.Xml.Serialization.XmlMapping[]#64844482=[160], ProxyEmergencyService.WSEmergency.Emergency#88831384=ProxyEmergencyService.WSEmergency.Emergency) 调用者:System.Web.Services.Protocols.SoapClientType#46729429::.ctor(ProxyEmergencyService.WSEmergency.Emergency#88831384=ProxyEmergencyService.WSEmergency.Emergency) 进程 ID=1456 逻辑操作栈= 线程 ID=1 日期时间=2010-08-06T01:58:45.8572390Z 时间戳=47298680452 System.Web.Services.Asmx 信息:0:从 XmlSerializer 返回 [创建 XmlSerializer] 调用者:System.Web.Services.Protocols.SoapClientType#46729429::.ctor(ProxyEmergencyService.WSEmergency.Emergency#88831384=ProxyEmergencyService.WSEmergency.Emergency) 进程 ID=1456 逻辑操作栈= 线程 ID=1 日期时间=2010-08-06T01:58:45.9353525Z 时间戳=47298924420 System.Web.Services.Asmx 信息:0:调用 XmlSerializer [写入请求] 方法:Microsoft.Xml.Serialization.GeneratedAssembly.ArrayOfObjectSerializer192#13256970::Serialize(System.Xml.XmlTextWriter#52203868=.., System.Object[]#72766=[1], (null), (null)) 调用者:ProxyZipeeeService.WSZipeee.Zipeee#654897::Serialize() 进程 ID=1456 逻辑操作栈= 线程 ID=1 日期时间=2010-08-06T01:58:46.0915795Z 时间戳=47299598906 System.Web.Services.Asmx 信息:0:从 XmlSerializer 返回 [Write Request] 调用者:ProxyZipeeeService.WSZipeee.Zipeee#654897::Serialize() 进程 ID=1456 逻辑操作栈= 线程 ID=1 日期时间=2010-08-06T01:58:46.0915795Z 时间戳=47299606361 System.Web.Services.Asmx 信息:0:调用 WebRequest.GetResponse 方法:System.Net.HttpWebRequest#5894079::GetResponse() 调用者:ProxyZipeeeService.WSZipeee.Zipeee#654897::GetWebResponse() 进程 ID=1456 逻辑操作栈= 线程 ID=1 日期时间=2010-08-06T01:58:46.0915795Z 时间戳=47299607492 System.Web.Services.Asmx 错误:0:ProxyZipeeeService.WSZipeee.Zipeee#654897::GetWebResponse 中捕获的异常。 System.Net.WebException:远程服务器返回错误:(400)错误请求。 进程 ID=1456 逻辑操作栈= 线程 ID=1 日期时间=2010-08-06T01:58:46.0915795Z 时间戳=47299629487 System.Web.Services.Asmx 错误:0:异常详细信息: System.Net.WebException:远程服务器返回错误:(400)错误请求。 在 System.Net.HttpWebRequest.GetResponse() 在 System.Web.Services.Protocols.WebClientProtocol.GetWebResponse(WebRequest 请求) 进程 ID=1456 逻辑操作栈= 线程 ID=1 日期时间=2010-08-06T01:58:46.0915795Z 时间戳=47299654807 System.Web.Services.Asmx 信息:0:调用 XmlSerializer [写入请求] 方法:Microsoft.Xml.Serialization.GeneratedAssembly.ArrayOfObjectSerializer192#13256970::Serialize(System.Xml.XmlTextWriter#53046711=.., System.Object[]#7658356=[1], (null), (null)) 调用者:ProxyZipeeeService.WSZipeee.Zipeee#1816341::Serialize() 进程 ID=1456 逻辑操作栈= 线程 ID=1 日期时间=2010-08-06T01:58:56.9024879Z 时间戳=47338202360

【问题讨论】:

    标签: asp.net iis-6 asmx webservices-client


    【解决方案1】:

    如上所述,主站点使用代理 DLL 与 Web 服务进行通信。在 Visual Studio 中,每个代理项目都有一个 Web 引用(.wsdl 文件等)和一个生成的 app.config 文件。在这 2 个代理项目之一中,app.config 文件保留了原始设置(这当然适用于我的桌面开发机器和暂存 Web 服务器):

    <applicationSettings>
        <ProxyZipeeeService.My.MySettings>
            <setting name="ProxyZipeeeService_WSZipeee_Zipeee" serializeAs="String">
                <value>http://localhost/ZipeeeWebService/Zipeee.asmx</value>
            </setting>
        </ProxyZipeeeService.My.MySettings>
    </applicationSettings>
    

    注意上面的 localhost 值。

    事实证明,当部署到生产服务器时,默认网站和同一台 IIS 机器上的另一个网站都有一个主机头值。后来我发现了更多关于这个设置的后果,并意识到当主站点尝试通过 localhost 访问 Web 服务时它失败了,因为在 2 个主机头值中找不到 localhost。因此,回到 Vstudio 并按如下方式更改 Web 参考可以解决问题:

    <applicationSettings>
        <ProxyZipeeeService.My.MySettings>
            <setting name="ProxyZipeeeService_WSZipeee_Zipeee" serializeAs="String">
                <value>http://www.zipeee.com/ZipeeeWebService/Zipeee.asmx</value>
            </setting>
        </ProxyZipeeeService.My.MySettings>
    </applicationSettings>
    

    【讨论】:

      【解决方案2】:

      尝试执行以下操作: 1. 添加一个名为 wsZipeee 的新服务引用,指向 Web 服务 2. 从调用位置(另一个 Web 应用程序、Winform 等):

      Dim ws as New wsZipeee.ZipeeeSoapClient()
      Dim dsStandardMsg As DataSet 
      dsStandardMsg = ws.GetMessageByType(BizConstants.MsgType.Standard)
      

      通过创建新的服务引用,这将处理代理并允许您干净地调用它。我假设您要调用的服务引用、Web 服务和方法的名称

      【讨论】:

      • 非常感谢您的建议。服务参考和 ZipeeeSoapClient 向我建议 WCF。我正在使用 ASMX,此时无法转换。 WS1 是我对 ZipeeeWebService 的简写,对它的调用似乎是失败的。 WS2 只是另一个 web 服务的简写(这里不是问题)。也许我误解了你的想法??
      猜你喜欢
      • 2012-01-19
      • 2013-07-21
      • 2010-10-21
      • 1970-01-01
      • 1970-01-01
      • 2012-06-27
      • 2020-10-21
      • 2019-06-18
      • 2015-04-10
      相关资源
      最近更新 更多