1

我有 2 个站点。

我也有一个网络服务。

当我在级联下拉列表中加载国家/地区名称时,您可以看到这一点:http ://www.mydomain.com/trouwlocaties/zoeken-uitgebreid

但是,相同的 Web 服务在以下位置引发错误: http: //otherdomain.com/weddingvenues/search-advanced 正如您所看到的下拉菜单显示“方法错误 -1”,在我的 Chrome 控制台中我看到:500(内部服务器错误) ,客户端尝试获取 .asmx 服务,在 toptrouwen 上它使用 POST(这是我相信应该发生的事情并且也更安全)。

这是 GetCountries 网络服务:

<System.Web.Script.Services.ScriptService()> _
<System.Web.Services.WebService(Namespace:="http://tempuri.org/")> _
<System.Web.Services.WebServiceBinding(ConformsTo:=WsiProfiles.BasicProfile1_1)> _
<Global.Microsoft.VisualBasic.CompilerServices.DesignerGenerated()> _
<ToolboxItem(False)> _
Public Class geolocation
'<System.Web.Script.Services.ScriptService()> _
'<WebService(Namespace:="http://tempuri.org/")> _
'<WebServiceBinding(ConformsTo:=WsiProfiles.BasicProfile1_1)> _
'<Global.Microsoft.VisualBasic.CompilerServices.DesignerGenerated()> _


Inherits System.Web.Services.WebService

<WebMethod()> _
Public Function GetCountries(ByVal knownCategoryValues As String, ByVal category As String) As CascadingDropDownNameValue()
    Dim values As New List(Of CascadingDropDownNameValue)

    Dim myConnection As SqlConnection = GetConnection()
    Dim cmd As New SqlCommand(String.Format("SELECT id,name as title FROM country order by title asc", Threading.Thread.CurrentThread.CurrentCulture.TwoLetterISOLanguageName), myConnection)
    Try
        myConnection.Open()
        Dim reader As SqlDataReader = cmd.ExecuteReader
        Dim CountryName As String
        Dim CountryID As Integer
        While reader.Read
            CountryName = reader("title").ToString
            Int32.TryParse(reader("id"), CountryID)
            values.Add(New CascadingDropDownNameValue(CountryName, CountryID.ToString))
        End While
    Catch ex As Exception

    Finally
        myConnection.Close()
    End Try

    Return values.ToArray
End Function

End Class   

首先,我尝试将其添加到我的 web.config 中:

<system.web>
<webServices>
  <protocols>
    <remove name="Documentation"/>
    <add name="HttpGet"/>
    <add name="HttpPost"/>
  </protocols>
</webServices>
</system.web>

之后,我在我的 Chrome 控制台中收到了这个:

Uncaught SyntaxError: Unexpected token < 

显然结果没有被解释为 XML,但我的猜测是 JSON。经过一些 Google 搜索后,我认为这与 MIME 类型有关,但我从未发现如何将其更改为 XML 以用于该服务。

所以我继续搜索,发现了别的东西,我正在阅读这些帖子: http : //social.msdn.microsoft.com/forums/en-us/asmxandxml/thread/F80BDA62-C87A-4BDA-8CB1-F2CFAD1C8891 Uncaught SyntaxError: Unexpected令牌 < -- 在 jQuery ajax 中

显然这可能是一个“跨域问题”。

所以我最终创建了这些文件:

客户端访问策略.xml

<?xml version="1.0" encoding="utf-8"?>
<access-policy>
  <cross-domain-access>
<policy>
  <allow-from http-request-headers="*">
    <domain uri="*"/>
  </allow-from>
  <grant-to>
    <resource path="/" include-subpaths="true"/>
  </grant-to>
</policy>
  </cross-domain-access>
</access-policy>

跨域.xml

<?xml version="1.0"?>
<!DOCTYPE cross-domain-policy SYSTEM "http://www.macromedia.com/xml/dtds/cross-domain-policy.dtd">
<?xml version="1.0" ?> 
<cross-domain-policy>
    <allow-access-from domain="*" /> 
    <allow-access-from domain="*.otherdomain.com" secure="false" /> 
</cross-domain-policy>

<configuration>
    <system.serviceModel>
        <bindings>
            <basicHttpBinding>
            <binding name="GetCountries" maxBufferSize="2147483647" maxReceivedMessageSize="2147483647"> 
                <security mode="None" />
            </binding>
            </basicHttpBinding>
        </bindings>
        <client>
            <endpoint address="http://www.mydomain.com/geolocation.asmx"
            binding="basicHttpBinding" name="GeoLocation" />
        </client>
    </system.serviceModel>
</configuration> 

在第一个示例链接中,用户还添加了属性 bindingConfiguration="DashboardServiceSoap" 和 contract="DashboardService.DashboardServiceSoap",但我不知道我必须为我的案例填写什么。

我仍然卡住了,我不知道什么是正确的轨道以及如何配置我的设置。

更新 21-06-2013

将我的 web.config 更新为:

<system.webServer>
    <httpProtocol>
        <customHeaders>
            <add name="Access-Control-Allow-Origin" value="*" />
            <add name="Access-Control-Allow-Headers" value="Content-Type" />
      </customHeaders>
    </httpProtocol>

我还尝试了以下 4 种配置:

<System.Web.Script.Services.ScriptService()> _
<System.Web.Services.WebService(Namespace:="http://tempuri.org/")> _
<System.Web.Services.WebServiceBinding(ConformsTo:=WsiProfiles.BasicProfile1_1)> _
<Global.Microsoft.VisualBasic.CompilerServices.DesignerGenerated()> _
<ToolboxItem(False)> _
Public Class geolocation

    Inherits System.Web.Services.WebService

场景 1 和 2 使用此方法定义:

<WebMethod()> _
Public Function GetCountries(ByVal knownCategoryValues As String, ByVal category As String) As CascadingDropDownNameValue() 

场景 1:web.config 中的 WITH 协议部分

<webServices>
  <protocols>
    <remove name="Documentation"/>
    <add name="HttpGet"/>
    <add name="HttpPost"/>
  </protocols>
</webServices>  

在 .nl 域上工作正确 在 .com 域上引发方法错误 -1。Chrome 控制台显示:Uncaught SyntaxError: Unexpected token < GetCountries:1

场景 2:web.config 中没有协议部分

在 .nl 域上工作正确 在 .com 域上引发方法错误 -1。Chrome 控制台显示:GET http://www.otherdomain.com/geolocation.asmx/GetCountries?knownCategoryValues=%22%22&category=%22Country%22&callback=Sys._jsonp0 500 (Internal Server Error) ScriptResource.axd:7773

使用此方法定义的场景 3 和 4:

<WebMethod()> _
<ScriptMethod(UseHttpGet:=True, ResponseFormat:=System.ServiceModel.Web.WebMessageFormat.Json)> _
Public Function GetCountries(ByVal knownCategoryValues As String, ByVal category As String) As CascadingDropDownNameValue() 

场景 3:web.config 中的 WITH 协议部分

<webServices>
  <protocols>
    <remove name="Documentation"/>
    <add name="HttpGet"/>
    <add name="HttpPost"/>
  </protocols>
</webServices>  

在 .nl 域上引发方法错误 500。Chrome 控制台显示:POST http://www.mydomain.com/geolocation.asmx/GetCountries 500(内部服务器错误) catcher.js:197 在下拉列表中的 .com 域上引发方法错误 -1。Chrome 控制台显示:Uncaught SyntaxError: Unexpected token < GetCountries:1

场景 4:web.config 中没有协议部分

在 .nl 域上引发方法错误 500。Chrome 控制台显示:加载资源失败:服务器响应状态为 500(内部服务器错误)在下拉列表中的 .com 域上引发方法错误 -1。Chrome 控制台显示:GET http://www.otherdomain.com/geolocation.asmx/GetCountries?knownCategoryValues=%22%22&category=%22Country%22&callback=Sys._jsonp0 500(内部服务器错误)

此外,我没有明确地从脚本中调用 .asmx,我让级联下拉菜单为我工作。像这样:

<asp:DropDownList ID="ddlCountries" CssClass="textbox" AutoPostBack="true" runat="server"></asp:DropDownList>
<cc1:cascadingdropdown ID="cddCountries" runat="server" Category="Country" Enabled="True" LoadingText="<%$Resources:Glossary,loading %>" PromptText="<%$Resources:Glossary,country_choose %>" 
ServiceMethod="GetCountries" TargetControlID="ddlCountries">
</cc1:cascadingdropdown>

代码隐藏

cddCountries.ServicePath = "http://www.mydomain.com/geolocation.asmx"

我不知道我使用这些预定义元素的事实是否与我的问题有关,我最好自己通过脚本调用 .asmx 服务并填写下拉列表。如果是这样:我不知道该怎么做。

4

1 回答 1

1

你说得对,这是一个跨域问题。有几种处理方法:

  1. 只要需要传输到 Web 服务的数据不是非常大,您就可以将您的 Web 服务转换为 JSONP。不过,来自服务的数据可以随心所欲。由于不是很大,它必须是大约 2k 个字符或更少 - 您可以通过知道它是作为脚本标记的 src 属性的 get 请求的一部分发送来计算可以在一个 JSONP 请求中发送的数据量。

    这是您可能已经熟悉的关于 JSONP 的一个很好的 SO 答案:

    JSONP 到底是什么?

    更新

    下面是一个在 VB.NET 中做 JSONP 的例子:

    http://www.sattsoft.com/tutorials/contents/1/14/cross-domain-call-using-ajax-jquery-jsonp-and-vb-net-web-service.html

  2. 您可以创建 www.wunderweddings.com 的子域,将其命名为“api.www.wunderweddings.com”并使用 DNS 使用 A 或 CNAME 记录将该子域指向正确的位置。然后你会在你的客户端页面中嵌入一个小的(不可见的)iframe,它会指向这个新的 api 主机(确保将 src 指定为“//api.www.underweddings.com”以匹配 http/s包含页面的),并在 iframe 中使用 javascript 将其 document.domain 提升为 www.wunderweddings.com,您可以通过脚本注入来执行此操作,但更容易让服务器上的该页面提供脚本来执行此操作,然后您可以在指向您的 api 的 iframe 和包含 iframe 的页面之间自由通信,该页面位于 www.wunderweddings.com。

  3. 如果您知道 postMessage 在您的客户端上始终可用(可能不是),您可以在不更改 document.domain 的情况下执行上述操作。

  4. 上面的第 2 点和第 3 点可能听起来很麻烦!特别是如果您打算扩展您提供的 Web 服务和/或访问该服务的域数量。如果是这样,我强烈推荐使用 EasyXDM,它是一个用于执行客户端跨域 RPC 的出色且功能强大的库:

    http://easyxdm.net/wp/

    如果 postMessage 不可用,EasyXDM 会提供后备方案,例如通过散列或名称属性进行通信等。

  5. 您可以修复 crossdomain.xml。现在这是我有点生疏的地方,但我会给你我最好的猜测:

更新

您希望您的 crossdomain.xml 像这样:

<?xml version="1.0" ?> 
<cross-domain-policy>
    <allow-access-from domain="*" /> 
    <allow-access-from domain="*.wunderweddings.com" /> 
</cross-domain-policy>

"<cross-domain-policy>" 的第一个孩子,即 "<allow-access-from domain=" " />" 将使其完全不受限制,而 "<allow-access-from domain=" .wunderweddings。 com" />" 将使浏览器只允许 wunderweddings.com 和子域进行跨域调用。您不需要两个“allow-access-from”标签,但至少需要其中一个。

我不知道为什么配置的东西在那里,它不应该在那里。我完全没有注意到第一次,这几乎肯定是你的问题。还要确保 crossdomain.xml 是从另一台服务器提供的,即具有 Web 服务的服务器。

所以澄清一下,crossdomain.xml 的底部不应该有那个额外的 XML,<onfiguration>...</configuration> 标签和它里面的所有东西,所有这些都是从某个地方泄漏的,不应该是在crossdomain.xml里面


最后更新

对于那些阅读此答案并有类似问题的人,Floran 发现了无效字符的问题:

这必须添加到页面顶部:

<asp:ScriptManagerProxy ID="ScriptManagerProxy1" runat="server"> 
<Services> 
<asp:ServiceReference Path="geolocation.asmx" /> 
</Services> 
</asp:ScriptManagerProxy>

于 2013-06-20T12:28:39.920 回答