【问题标题】:Load custom configuration file in WCF relative to Working Directory在 WCF 中加载相对于工作目录的自定义配置文件
【发布时间】:2011-09-29 13:55:03
【问题描述】:

我有一个 WCF 服务库,它读取位于 WCF 发布位置的 xml 文件。该项目不是客户资料。

当我在 WCF 测试客户端中调试时,它可以正常工作:

XDocument xDoc = XDocument.Load(@".\PaymentAvailability.xml");

但是当从一个网站使用该服务时,它说它找不到 PaymentAvailability.xml ......它看起来像是试图从使用应用程序获取 xml 文件的位置。

我已经尝试过这里发布的答案,但没有运气How to get working path of a wcf application?

System.Web.Hosting.HostingEnvironment.ApplicationPhysicalPath 返回空值

使用 AspNetCompatability HttpContext.Current.Server.MapPath("."); 也不会返回任何内容

【问题讨论】:

  • 完整的异常消息是什么,它是否显示了它正在搜索的完整路径?
  • 找不到文件'c:\windows\system32\inetsrv\PaymentAvailability.xml'。

标签: .net wcf configuration


【解决方案1】:

这是一个真的不好的做法,你应该将你的库的配置放在使用你的库的应用程序的 .config 文件中,使用自定义部分处理程序(Configuration Section Designer 确实非常非常适合你)如果你想要强类型的 XML 配置。

原因是您正在配置的是您的应用程序;如果您的库真的独立于您的应用程序运行,那么您应该重新考虑该库是否不应该是它自己的应用程序。

您必须缓解此问题以创建自定义配置部分处理程序,然后使用configSource attribute。虽然您将无法使用单个文件(该属性不允许使用绝对路径),但您可以将一个文件复制到每个应用程序的 bin 目录中。

请注意,您必须明确获取配置部分,但无论如何您现在都必须这样做才能加载文件,但至少您会更符合配置管理器。

【讨论】:

  • 消费应用应该做什么? XML 文件路径? - 但是使用该 WCF 服务的每个应用程序都将从同一个 xml 文件中读取。尽管如此,我肯定会读入配置部分,因为我不熟悉(WCF 的新手)。 PaymentAvailability xml 文件告诉消费应用程序是否有其他 WCF 支付服务可用(例如,如果 PayPal 已安排停机时间,我可以在 xml 文件中列出,消费站点将禁用 PayPal 作为支付选项)-> 这将是使用了我的多个网站,并轻松地允许我使用 1 个文件在一堆网站上禁用付款
  • 所以说真的,我想它可以被认为是一种配置,但它必须在多个站点之间共享......我不会手动更新 10 个 web.configs :p
  • @Chris Klepeis:是的,如果您有 N 个站点,那么这 N 个站点应该有自己的配置,并且应该将其复制到配置文件中。您也可以使用configuSource 属性;有关更多信息,请参阅我的更新答案。
  • 我同意这可能是一个不好的做法,但是,(如果我在这里错了,请纠正我)但是如果我在 bin 目录中更新该文件,因为它是配置的一部分,那么应用程序将重新启动 - 终止我们的会话(我们在重新启动之间没有会话持久性)。由于它是一个高流量站点,我们希望尽可能减少这种情况,直到我们可以设置会话持久性
  • @ChrisKlepeis:如果您在 ASP.NET 会话中托管,并且您使用 configSource 属性,是的,它将导致创建一个新的应用程序域和旧的应用程序域(使用它会话状态)消失。但是,如果您有负载平衡,内存中的会话状态会杀死您(您应该使用会话状态服务器或 sql 服务器作为会话状态管理器来防止这种情况发生)。
【解决方案2】:

一般

System.Reflection.Assembly.GetExecutingAssembly().Location

为您提供执行程序集的物理路径。

msdn 页面上,您可以看到 GetExecutingAssembly、GetEntryAssembly 和 GetCallingAssembly 之间的区别。

也就是说,无论如何这可能不是一个好主意(请参阅casperOne's answer)。

【讨论】:

    【解决方案3】:

    这行得通,但从其他答案来看,我将看看这是否确实是一种不好的做法,是否可以做得更好。

    ServiceHostBase hostBase = OperationContext.Current.Host;
    VirtualPathExtension virtualPathExtension = hostBase.Extensions.
        Find<VirtualPathExtension>();
    
    XDocument xDoc;
    
    if (virtualPathExtension != null)
    {
        /// It’s hosted.
        xDoc = XDocument.Load(Path.Combine(
            HostingEnvironment.ApplicationPhysicalPath, AvailabilityFileName));
    }
    else
    {
        /// It’s not hosted.
        xDoc = XDocument.Load(AvailabilityFileName);
    }
    

    【讨论】:

    • 这是一种更糟糕的做法;像这样的功能不应该是自我意识的;他们需要的东西应该传递给他们,图书馆应该使用它。在这种情况下,如果调用者正在调用库,它知道它在一个主机中(如果它没有,那么 那个 代码有问题),如果它不在一个主机中,它知道它是不是。然后,调用者应该告诉库在哪里查找文件。
    猜你喜欢
    • 1970-01-01
    • 2010-10-05
    • 2016-03-04
    • 1970-01-01
    • 1970-01-01
    • 2012-02-11
    • 2014-05-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多