使用WcfSvcHost进行跨域异常

时间:2010-02-24 13:36:27

标签: c# wcf silverlight

抱歉另一个跨域问题。

我现在一整天都在和这个人打架,现在已经沸腾了。

我有一个Silverlight应用程序项目(SLApp1),一个用于托管Silverlight(SLApp1.Web)和WCF项目(SLWcfService)的Web项目。

现在我正在一起构建所有项目,所有项目都在一个解决方案中。 Web项目由Visual Studio托管,WCF服务由WcfSvcHost托管。

由于web和wcf单独托管存在跨域问题,因此每次我的Silverlight应用程序尝试调用WCF时都会抛出跨域异常。

我试过了:

  1. 将clientaccesspolicy.xml添加到C:\ inetpud \ wwwroot
  2. 使用webHttpBinding并在服务中使用ReadPolicy方法
  3. 问题是我仍在开发解决方案,因此发布服务然后在IIS中托管根本不是一个可行的解决方案。

    为什么这一点难以置信?

    请帮助!

    参考资料:

    我的App.config:

         <system.serviceModel>
        <services>
          <service name="Test.Service1" behaviorConfiguration="Test.Service1Behavior">
            <host>
              <baseAddresses>
                <add baseAddress="http://localhost:8055" />
              </baseAddresses>
            </host>
            <endpoint address="Service1" binding="basicHttpBinding" contract="Test.IService1"/>
            <endpoint address="" binding="webHttpBinding" behaviorConfiguration="webHttpBehavior" contract="Test.WCFService.IClientAccessPolicy" />
            <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
          </service>
        </services>
        <behaviors>
          <serviceBehaviors>
            <behavior name="Test.WCFService.Service1Behavior">
              <serviceMetadata httpGetEnabled="True" />
              <serviceDebug includeExceptionDetailInFaults="False" />
            </behavior>
          </serviceBehaviors>
          <endpointBehaviors>
            <behavior name="webHttpBehavior">
              <webHttp/>
            </behavior>
          </endpointBehaviors>
        </behaviors>
      </system.serviceModel>
    

4 个答案:

答案 0 :(得分:1)

虽然我不确定这会解决您的问题,但我会告诉您如何设法修复类似的解决方案布局,并且可能会采取一些指导措施。

我使用silverlight项目(domainexception),web项目(domainexception.Web)和wcf服务(WcfServiceLibrary1)设置了解决方案。我使Service1端点成为一个basicHttpBinding,就像它在你的App.config中一样。

然后我添加了一个对silverlight项目的服务引用,并使用以下地址构建它:

  

http://localhost:8731/Design_Time_Addresses/WcfServiceLibrary1/Service1/

尝试像这样运行它我也遇到了跨域策略问题。

然后我将webHttpBinding和方法添加到它,仍然发现它不起作用。

所以,最后我将基地址从上面的地址改为

  

http://localhost:8731

并且有效。

最终有效。所以这就是它最后的样子。

<强>的App.config

 <system.serviceModel>
<services>
  <service name="WcfServiceLibrary1.Service1" behaviorConfiguration="WcfServiceLibrary1.Service1Behavior">
    <host>
      <baseAddresses>
        <add baseAddress = "http://localhost:8731/" />
      </baseAddresses>
    </host>
    <endpoint address ="Service" binding="basicHttpBinding" contract="WcfServiceLibrary1.IService1">
      <identity>
        <dns value="localhost"/>
      </identity>
    </endpoint>
    <endpoint address="" binding="webHttpBinding" behaviorConfiguration="policyBehavior" contract="WcfServiceLibrary1.IService1"/>
    <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
  </service>
</services>
<behaviors>
  <endpointBehaviors>
    <behavior name="policyBehavior">
      <webHttp />
    </behavior>
  </endpointBehaviors>
  <serviceBehaviors>
    <behavior name="WcfServiceLibrary1.Service1Behavior">
      <serviceMetadata httpGetEnabled="True"/>
      <serviceDebug includeExceptionDetailInFaults="False" />
    </behavior>
  </serviceBehaviors>
</behaviors>

<强> ServiceReferences.ClientConfig

<configuration>
<system.serviceModel>
    <bindings>
        <basicHttpBinding>
            <binding name="BasicHttpBinding_IService1" maxBufferSize="2147483647"
                maxReceivedMessageSize="2147483647">
                <security mode="None" />
            </binding>
        </basicHttpBinding>
    </bindings>
    <client>
        <endpoint address="http://localhost:8731/Service" binding="basicHttpBinding"
            bindingConfiguration="BasicHttpBinding_IService1" contract="ServiceReference1.IService1"
            name="BasicHttpBinding_IService1" />
    </client>
</system.serviceModel>

以及我对该政策的网络呼吁:

<强>接口

[OperationContract, WebGet(UriTemplate="clientaccesspolicy.xml")]
    Stream ReturnPolicy();

<强>代码

public System.IO.Stream ReturnPolicy()
    {
        string file = @"<?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>";
        return new MemoryStream(Encoding.UTF8.GetBytes(file));
    }

答案 1 :(得分:0)

前一段时间我也面临同样的问题。我得出的结论是,时间是在WebProject(托管Silverlight控件)中引用WCFService项目的dll,并根据WCFService更改了它的web.config。然后我没有使用WcfSvcHost参考,而是使用了WebProject的参考资料,这就是我使用过的解决方法。

但简而言之,在WCFSvcHost托管的服务上应用客户端访问策略有点棘手。

答案 2 :(得分:0)

好吧,不知何故,我使用REST和webHttpBinding技巧。我对如何从读取的文件读取clientaccesspolicy到只使用cons字符串进行了更改。

以下是我解决问题的方法:

<强> App.config中:

 <system.serviceModel>
<services>
  <service name="Symphony.Server.WCFService.Service1" behaviorConfiguration="Symphony.Server.WCFService.Service1Behavior">
    <host>
      <baseAddresses>
        <add baseAddress="http://localhost:8055" />
      </baseAddresses>
    </host>
    <endpoint address="Service1" binding="basicHttpBinding" contract="Symphony.Server.WCFService.IService1"/>
    <endpoint address="" binding="webHttpBinding" behaviorConfiguration="webHttpBehavior" contract="Symphony.Server.WCFService.IClientAccessPolicy" />
    <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
  </service>
</services>
<behaviors>
  <serviceBehaviors>
    <behavior name="Symphony.Server.WCFService.Service1Behavior">
      <serviceMetadata httpGetEnabled="True" />
      <serviceDebug includeExceptionDetailInFaults="False" />
    </behavior>
  </serviceBehaviors>
  <endpointBehaviors>
    <behavior name="webHttpBehavior">
      <webHttp/>
    </behavior>
  </endpointBehaviors>
</behaviors>

<强> IClientAccessPolicy.cs

[ServiceContract]
public interface IClientAccessPolicy
{
    [OperationContract, WebGet(UriTemplate = "/clientaccesspolicy.xml")]
    Stream GetPolicy();
}

<强> Service1.cs

public class Service1 : IService1, IClientAccessPolicy
{
    public IList<string> GetData(string value)
    {
        //Some logic
    }

    [OperationBehavior]
    public Stream GetPolicy()
    {
        const string result = @"<?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>";

        if (WebOperationContext.Current != null)
            WebOperationContext.Current.OutgoingResponse.ContentType = "application/xml";
        return new MemoryStream(Encoding.UTF8.GetBytes(result));
    }

注意: 您必须包含System.ServiceModel.Web作为参考

谢谢

答案 3 :(得分:0)

WCFService Project中的PolicyService(REST)可以解决这个问题。这种服务允许 在Response中发送xml(clientAccessPolicy)。例如,如果您的服务网址如下: http://localhost:[port]/Design_Time_Addresses/MyService.svc

然后PolicyService URL将是: http://localhost:[port]/clientaccesspolicy.xml(这种REST请求将在响应SilverlightClient时发送clientaccesspolicy)。

以下是有关如何创建此类PolicyService的链接: http://social.msdn.microsoft.com/Forums/en/wcf/thread/d145a38f-b9bb-4c8e-9eab-b728dacc19df