【问题标题】:WCF : Is it possible to move all service settings outside the config file, and in the code?WCF:是否可以将所有服务设置移到配置文件之外和代码中?
【发布时间】:2011-03-05 13:15:35
【问题描述】:

我有一个使用了一年多的 WCF,由其他人编码,我正在尝试重构它,但文件夹结构的组织方式和包含方法的 svc.cs 文件不是我的习惯了 WCF 示例我 completed.

这就是我想要实现的目标。由于去年没有更改任何设置,因此我被要求将所有服务设置硬编码为代码。该服务托管在大型现有 Web 应用程序中(我必须将其保留在那里),svc 文件包含客户端调用的方法,并且此 svc.cs 文件不位于虚拟目录的根目录,而是更深入一点,比如说<virtualDirectory>/WebServices/PotatoWebService/PotatoWebService.svc,让它不在虚拟目录根目录中会不会导致任何问题?

由于我将配置从配置文件中移出,我现在正在 Web 应用程序的 global.axax.cs 文件中创建服务、主机、端点、绑定,地址为 ApplicationStart(),这是正确的起点Web 应用程序中的此服务?

是否可以移动代码中的所有内容,不仅是端点,还包括 web.config 文件中的行为、服务和 system.ServiceModel 的全部内容,以便“清理”配置文件并停止用他们不需要的设置吓唬支持和配置经理?

如果是这样,我已经尝试了 2 天来让它工作但没有成功。根据 netstat,我现在拥有的是一个正在运行的服务,但是当我在浏览器中打开我的 svc 文件时,会弹出一个异常,提示该服务定义了任何端点,尽管根据 nstat 我有一个正在运行的服务:

netstat -a | find LISTENING

...
  TCP    machineName:8097      elamontagne.potato.com:0  LISTENING
...

所以我有一个服务正在运行,但是一个 svc 文件不知道它并且不能使用它的端点,一个客户端试图联系该服务并且由于服务没有端点而找不到它,任何缩小范围的提示解决问题,解决这种情况的提示?

     //Address
    string hostingAddress = "PotatoVirtualDirectory/PotatoService/PotatoService.svc";   
    // Binding
    BasicHttpBinding PotatoServiceBinding = ConfigurePotatoServiceBinding(serviceSecurityMode);
    // Contract
    Type PotatoContract = typeof(IPotatoService);
    // Host
    this.PotatoServiceHost = new ServiceHost(typeof(PotatoService), new Uri("http://localhost:8097"));
    // Endpoint
    this.PotatoServiceHost.AddServiceEndpoint(PotatoContract, PotatoBinding, hostingAddress);
    // Behavior
    ConfigurePotatoServiceBehavior(this.PotatoServiceHost, PotatoServiceBinding);
    // Name
    this.PotatoServiceHost.Description.Name = "PotatoNamespace.PotatoService";
    //Start!
    this.PotatoServiceHost.Open();

这编译并运行,它为我提供了一个处于打开状态的运行服务。客户端无法在其通常位置找到它,并且 svc 文件抱怨它在 web.config 中没有任何内容并想要一个端点 ServiceHasZeroAppEndpoints: "Service has zero application (non-infrastructure) endpoints"

我已经在调试中逐步完成了代码,一切看起来都很好,服务是开放的,我缺少什么,有什么技巧可以缩小这个问题的范围吗?

编辑:从服务主机工厂派生效果很好,谢谢!

【问题讨论】:

    标签: .net wcf .net-3.5


    【解决方案1】:

    您可以编写一个custom service host factory,您可以在其中以编程方式配置服务,而不是使用配置文件。然后在你的 .svc 标记文件中配置这个自定义工厂:

    <%@ServiceHost Factory="CustomFactory" Service="MyService" %>
    

    【讨论】:

    • 谢谢,但是否需要覆盖主机工厂,我是否在做超出标准 WCF 配置范围的事情?似乎我有一项服务,但我的客户无法调用它,因为他正在调用的 svc 文件没有找到已经启动并运行以供它使用的端点,我是否没有选项或者是否有我可以进行的故障排除步骤采用?因为所有的异常都告诉我没有找到端点
    • 标准方式是使用配置文件。如果您想以编程方式执行此操作,那么是的,您可能需要编写一个自定义主机工厂来指示端点的设置。客户得到的确切异常是什么?你能调用网络服务吗?
    • 我已经取得了一些进展,客户不再收到异常。一个小时前写的时候,客户端无法调用服务,说svc没有endPoint。现在它可以调用但不能更新服务引用。它调用构造函数 ServiceClient(System.ServiceModel.Channels.Binding binding, System.ServiceModel.EndpointAddress remoteAddress) : base(binding, remoteAddress) 并且端点地址是 svc 文件之一,文本包括 svc 扩展名,我希望我是能够在浏览器中打开它,我绝对需要一个 mex 端点来打开这个页面吗?
    • 只是为了澄清一下,客户端调用并收到正常操作的答案。它所属的库有一个指向 svc 文件的服务引用。如果我尝试更新服务引用,它还说没有找到端点,使用 .Open() 开头的 ServiceHost 的 svc 文件是否矛盾?我现在正在进一步阅读详细信息,看看我是否误解了托管模型,但如果您能对正在发生的事情有所了解,我们将不胜感激。
    【解决方案2】:

    在 ApplicationStart() 处,是 启动此服务的正确位置 在 Web 应用程序中?

    没有。您不能同时拥有由 ASP.NET 运行时托管和通过代码显式托管。但是你可以像 Darin 描述的那样声明一个自定义服务工厂。

    它不在虚拟目录根目录中会导致任何问题吗?

    没问题。

    另外,请问为什么要以编程方式执行此操作?编写和测试所有代码不是很痛苦吗?如果您只是不喜欢 Web.config 文件中的那一大块 WCF 配置,您可以将 WCF 配置放入单独的配置文件中。

    通常,WCF 服务的配置方式始终相同。无论是自托管还是 IIS 托管都没有区别。 ServiceHost 有一个默认实现,您的服务描述和端点是如何构建的。默认情况下,它会尝试在应用程序配置文件中定位服务配置。在您的情况下,Web.config。自托管和IIS托管使用的ServiceHost完全一样。

    不同之处在于此 ServiceHost 的实例化方式。在自托管中,您可以完全控制,因为您必须自己创建 ServiceHost 的实例。在 IIS 托管方案中,ASP.NET 运行时将使用 ServiceHostFactory 来实例化您的服务主机。

    因此,如果您想手动配置您的 ServiceHost,您必须创建自己的 ServiceHostFactory 并在 SVC 文件中引用它。

    回到你的问题:

    如果我理解正确,web.config 中的设置会自动在 iis 进程中的 aspnet_wp.exe 中托管服务

    “托管”仅表示它在 Web 应用程序中运行。只要您将服务部署为 Web 应用程序的一部分,它就始终由 IIS 托管。无论您如何以及在何处配置它,都没有其他独立的可执行文件,

    并在客户端调用.svc文件时自动启动?

    在 ASP.NET Web 应用程序中,所有 HTTP 请求都通过 ASP.NET“管道”。管道有一组处理程序,它们将拾取和处理请求。对于 WCF,这是 System.ServiceModel.Activation.HttpHandler。这个处理程序,稍微简化,将检查它是否有一个有效的 ServiceHost,如果没有,则使用 ServiceHostFactory 创建一个。处理程序绝对不关心您是否已经在 Global.asax 中创建了 ServiceHost!

    如果我使用 global.axax.cs 中的 ServiceHost.Open() 启动它,它会显式启动它并且它不是由 iis 托管的。

    没有。您在 Web 应用程序中运行的任何代码都在 IIS 托管的应用程序域中运行。

    ,还是仍然由 IIS 托管但 svc 文件被忽略?

    是的。但更多的是反过来。您的 Global.asax 代码将被忽略,WCF 激活仍会尝试创建另一个服务主机。

    然后这里建议的第三个选项,一个派生自主机工厂的类,该类将从 svc 调用,并且服务将以与 web.config 中的设置相同的方式启动?

    这是唯一的选择。获取 RedGates Reflector(它是免费的)并反汇编 ServiceHostFactory 类。它相当小。你会看到你几乎可以从 Global.asax 那里复制过去的代码,你就完成了。 ...当然也应该有大量的文档...

    希望有帮助!

    【讨论】:

    • 这是一个很好的建议,我喜欢 wcf 配置的大块,但是支持设法把它搞砸了,配置经理说,因为它一年都没有改变,他想要退出web.config,因为它应该可以在设计上从一个移动到另一个。你是对的,这可能会改变服务并导致大量重新测试。
    • 如果我理解正确的话,web.config 中的设置会自动在 iis 进程中的 aspnet_wp.exe 中托管服务,并在客户端调用 .svc 文件时自动启动?如果我使用 global.axax.cs 中的 ServiceHost.Open() 启动它,这会显式启动它并且它不是由 iis 托管,还是仍然由 IIS 托管但 svc 文件被忽略?然后这里建议的第三个选项,一个派生自主机工厂的类,该类将从 svc 调用,并且服务将以与 web.config 中的设置相同的方式启动?
    • 感谢 Alex 的所有回答,这澄清了很多问题,我仍然想知道这两个服务中的哪一个(我的手动 ServiceHost 或由处理程序创建的一个)目前正在为来自的调用提供服务我的客户,然后我会看看 ServiceFactory,起初我确信这可以通过实例化一些与配置文件等效的对象来完成,现在在某些情况下它涉及更多,我会检查星期一出来,然后在这里报告进度,再次感谢。
    【解决方案3】:

    听起来您可以使用以下方法。

    您可以从网络配置中引用您自己的配置文件。 对于这个想法更进一步,看看Managing ASP.NET Development, Staging and Production Connection Strings (without pulling your hair out)

    <configuration>
        <appSettings>
            <add key="ServerConfigPath" value="~/ServerConfig.config"/>
        </appSettings>
    </configuration>
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-07-07
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多