为什么Azure的CloudConfigurationManager.GetSetting返回null



我有一个在模拟器中本地运行的云服务web角色项目,但在部署时不运行。给出的错误如下:

[ArgumentNullException: Value cannot be null.
Parameter name: connectionString]
   Microsoft.WindowsAzure.Storage.CloudStorageAccount.Parse(String connectionString) in e:projectsazure-sdk-for-netmicrosoft-azure-apiServicesStorageLibCommonCloudStorageAccount.cs:344
   Candor.WindowsAzure.Storage.Table.CloudTableProxy`1.GetTable() in c:Usersmicha_000DocumentsGitHubcandor-commonCandor.WindowsAzureStorageTableCloudTableProxy.cs:66
   Candor.WindowsAzure.Storage.Table.CloudTableProxy`1.Get(String partitionKey, String rowKey) in c:Usersmicha_000DocumentsGitHubcandor-commonCandor.WindowsAzureStorageTableCloudTableProxy.cs:117
   Candor.WindowsAzure.Logging.Common.Table.CloudTableLogger.get_Configuration() +218
   Candor.WindowsAzure.Logging.Common.Table.CloudTableLogger.get_IsInfoEnabled() +9
   Common.Logging.Factory.AbstractLogger.Info(Object message) in c:_osscommon-loggingsrcCommon.Logging.CoreLoggingFactoryAbstractLogger.cs:503
   Candor.Configuration.Provider.ProviderCollection`1.SetActiveProvider(T provider) in c:Usersmicha_000DocumentsGitHubcandor-commonCandorConfigurationProviderProviderCollection.cs:169
   Candor.Configuration.Provider.ProviderResolver`1.AppendActive(T provider) in c:Usersmicha_000DocumentsGitHubcandor-commonCandorConfigurationProviderProviderResolver.cs:77
   SHM.PublicMvcWeb.App_Start.ProviderBootstrapper.InitProviders() in c:Usersmicha_000DocumentsGit-Reposshm-mainSHM.PublicMvcWebApp_StartProviderBootstrapper.cs:23
   SHM.PublicMvcWeb.App_Start.ProviderBootstrapper.PostStartup() in c:Usersmicha_000DocumentsGit-Reposshm-mainSHM.PublicMvcWebApp_StartProviderBootstrapper.cs:18

您可以在github上的堆栈跟踪中看到相关行的代码。

https://github.com/michael-lang/candor-common/

在CloudTableProxy中导致错误的行是:

            if (String.IsNullOrWhiteSpace(_connectionName))
                throw new InvalidOperationException("The Cloud ConnectionName has not been configured.");
            if (_account == null)
                _account = CloudStorageAccount.Parse(CloudConfigurationManager.GetSetting(_connectionName));

因为它没有抛出自定义错误" the cloud connectionName has not configured.",这告诉我_connectionName传入CloudConfigurationManager。GetSetting不为空。因此,CloudConfigurationManager是为提供的名称返回null的调用。考虑到这个名字在本地运行时确实返回一个值,我不确定为什么部署到我的云web角色时找不到它。如果输入的连接名是一个错别字,那么它在本地也无法工作。为了确保这一点,下面是我常用的日志配置,命名要使用的连接:

  <common>
    <logging>
      <factoryAdapter type="Candor.WindowsAzure.Logging.Common.Table.CloudTableLoggerFactoryAdapter, Candor.WindowsAzure.Logging.Common">
        <arg key="connectionName" value="Microsoft.WindowsAzure.Plugins.Diagnostics.ConnectionString" />
      </factoryAdapter>
    </logging>
  </common>

我也有一个完全不同的解决方案,使用相同的Candor云服务web角色。常见的组件,所以我不认为它们是问题。

我使用同一台笔记本电脑来开发这两个解决方案,因此两者都使用Azure 2.2工具版本。检查每个解决方案中Cloud Service项目的属性可以验证这一点。

我检查了每个组件和NuGet包引用,以确保解决方案中没有版本不匹配。在工作解决方案和此非工作解决方案之间将相同的组件设置为copy-local=true。它们也具有相同的绑定重定向。虽然这是我最大的问题,现在解决了,在遇到这个连接问题之前。

非工作业务部署配置:

<?xml version="1.0" encoding="utf-8"?>
<ServiceConfiguration serviceName="SHM.AzureService.PublicMvcWeb" xmlns="http://schemas.microsoft.com/ServiceHosting/2008/10/ServiceConfiguration" osFamily="4" osVersion="*" schemaVersion="2013-10.2.2">
  <Role name="SHM.PublicMvcWeb">
    <Instances count="1" />
    <ConfigurationSettings>
      <Setting name="Microsoft.WindowsAzure.Plugins.Diagnostics.ConnectionString" value="DefaultEndpointsProtocol=https;AccountName=(redacted);AccountKey=(redacted)" />
      <Setting name="DefaultTableConnection" value="DefaultEndpointsProtocol=https;AccountName=(redacted);AccountKey=(redacted)" />
      <Setting name="UserTableConnection" value="DefaultEndpointsProtocol=https;AccountName=(redacted);AccountKey=(redacted)" />
      <Setting name="UserSaltTableConnection" value="DefaultEndpointsProtocol=https;AccountName=(redacted);AccountKey=(redacted)" />
      <Setting name="UserAuditTableConnection" value="DefaultEndpointsProtocol=https;AccountName=(redacted);AccountKey=(redacted)" />
    </ConfigurationSettings>
  </Role>
</ServiceConfiguration>

我最近也尝试把这些相同的连接名称在web应用程序的应用设置。这是对3年前的评论的回应,他们的代码在RoleEnvironment.OnStart之前执行。但是这个尝试仍然导致相同的错误。

尝试如下:

  <appSettings>
    <add key="webpages:Version" value="3.0.0.0" />
    <add key="webpages:Enabled" value="false" />
    <add key="ClientValidationEnabled" value="true" />
    <add key="UnobtrusiveJavaScriptEnabled" value="true" />
    <add key="Microsoft.WindowsAzure.Plugins.Diagnostics.ConnectionString" value="DefaultEndpointsProtocol=https;AccountName=(redacted);AccountKey=(redacted)"/>
    <add key="DefaultTableConnection" value="DefaultEndpointsProtocol=https;AccountName=(redacted);AccountKey=(redacted)"/>
    <add key="UserTableConnection" value="DefaultEndpointsProtocol=https;AccountName=(redacted);AccountKey=(redacted)"/>
    <add key="UserSaltTableConnection" value="DefaultEndpointsProtocol=https;AccountName=(redacted);AccountKey=(redacted)"/>
    <add key="UserAuditTableConnection" value="DefaultEndpointsProtocol=https;AccountName=(redacted);AccountKey=(redacted)"/>
  </appSettings>

这段错误代码确实在使用WebActivator 2.0.6的应用程序启动时运行,而我的工作解决方案使用WebActivator 2.0.4。但是WebActivator的发布说明只显示了编译从Debug到"零售"的变化,以及两个版本之间的许可变化,而这些变化是在一年前发生的。

如果时间是问题,我还尝试在错误调用之前添加一个Thread.Sleep(1000),它也不起作用,所以我要删除它。

using System.Threading;
using Candor.Configuration.Provider;
using Candor.Security;
using Candor.Security.Cryptography;
using Candor.Security.Web;
[assembly: WebActivatorEx.PreApplicationStartMethod(typeof(StopHarassingMe.PublicMvcWeb.App_Start.ProviderBootstrapper), "PreStartup")]
[assembly: WebActivatorEx.PostApplicationStartMethod(typeof(StopHarassingMe.PublicMvcWeb.App_Start.ProviderBootstrapper), "PostStartup")]
namespace SHM.PublicMvcWeb.App_Start
{
    public class ProviderBootstrapper
    {
        public static void PreStartup()
        {
        }
        public static void PostStartup()
        {
            Thread.Sleep(1000); //let RoleEnvironment finish startup first or connectionstrings are not available.
            InitProviders();
        }
        private static void InitProviders()
        {
            ProviderResolver<HashProvider>.Configure()
                .AppendActive(new SHA2HashProvider("sha2") { IsObsolete = false, SaltModifier = "" });
        }
    }
}

这是在工作和非工作解决方案中配置的第一个提供者。

下面是出错的web应用程序使用的包列表:

<?xml version="1.0" encoding="utf-8"?>
<packages>
  <package id="Antlr" version="3.5.0.2" targetFramework="net45" />
  <package id="Candor.Core" version="1.4.1.0" targetFramework="net45" />
  <package id="Candor.jQuery.AutoAsync" version="4.0.0.50129" targetFramework="net45" />
  <package id="Candor.Security" version="2.4.0.0" targetFramework="net451" />
  <package id="Candor.Security.AzureStorageProvider" version="2.3.2.0" targetFramework="net451" />
  <package id="Candor.Web.Mvc" version="1.0.3.0" targetFramework="net451" />
  <package id="Candor.Web.Mvc.ErrorHandler" version="1.0.0.0" targetFramework="net45" />
  <package id="Candor.Web.Mvc.Security" version="2.1.0.0" targetFramework="net45" />
  <package id="Candor.WindowsAzure" version="1.3.0.0" targetFramework="net451" />
  <package id="Candor.WindowsAzure.Logging.Common" version="1.1.1.0" targetFramework="net451" />
  <package id="Common.Logging" version="2.2.0" targetFramework="net45" />
  <package id="Common.Logging.Core" version="2.2.0" targetFramework="net45" />
  <package id="form2js" version="1.0.0.30224" targetFramework="net45" />
  <package id="jQuery" version="2.1.4" targetFramework="net451" />
  <package id="jQuery.UI.Combined" version="1.8.20.1" targetFramework="net45" />
  <package id="jQuery.Validation" version="1.13.1" targetFramework="net45" />
  <package id="MarkdownSharp" version="1.13.0.0" targetFramework="net451" />
  <package id="Microsoft.AspNet.Mvc" version="5.2.3" targetFramework="net45" />
  <package id="Microsoft.AspNet.Razor" version="3.2.3" targetFramework="net45" />
  <package id="Microsoft.AspNet.Web.Optimization" version="1.1.3" targetFramework="net45" />
  <package id="Microsoft.AspNet.WebApi" version="5.2.3" targetFramework="net45" />
  <package id="Microsoft.AspNet.WebApi.Client" version="5.2.3" targetFramework="net45" />
  <package id="Microsoft.AspNet.WebApi.Core" version="5.2.3" targetFramework="net45" />
  <package id="Microsoft.AspNet.WebApi.HelpPage" version="5.2.3" targetFramework="net451" />
  <package id="Microsoft.AspNet.WebApi.WebHost" version="5.2.3" targetFramework="net45" />
  <package id="Microsoft.AspNet.WebPages" version="3.2.3" targetFramework="net45" />
  <package id="Microsoft.Data.Edm" version="5.6.0" targetFramework="net451" />
  <package id="Microsoft.Data.OData" version="5.6.0" targetFramework="net451" />
  <package id="Microsoft.jQuery.Unobtrusive.Validation" version="3.2.3" targetFramework="net45" />
  <package id="Microsoft.Web.Infrastructure" version="1.0.0.0" targetFramework="net45" />
  <package id="Microsoft.WindowsAzure.ConfigurationManager" version="2.0.1.0" targetFramework="net45" />
  <package id="Modernizr" version="2.8.3" targetFramework="net45" />
  <package id="Newtonsoft.Json" version="6.0.8" targetFramework="net45" />
  <package id="Respond" version="1.4.2" targetFramework="net45" />
  <package id="RestSharp" version="105.0.1" targetFramework="net451" />
  <package id="System.Spatial" version="5.6.0" targetFramework="net451" />
  <package id="T4MVC" version="3.7.4" targetFramework="net45" />
  <package id="T4MVCExtensions" version="3.7.4" targetFramework="net45" />
  <package id="Twilio" version="4.0.3" targetFramework="net451" />
  <package id="Twilio.Mvc" version="3.1.15" targetFramework="net451" />
  <package id="Twilio.TwiML" version="3.3.6" targetFramework="net451" />
  <package id="WebActivatorEx" version="2.0.6" targetFramework="net451" />
  <package id="WebGrease" version="1.6.0" targetFramework="net45" />
  <package id="WindowsAzure.Storage" version="2.1.0.3" targetFramework="net45" />
</packages>

在我的工作解决方案和非工作解决方案之间有几个软件包差异,但我不认为这些适用于错误。我从MVC 5.0升级到5.2.3,升级了javascript相关包,还有Candor。WindowsAzure从1.2.10到1.3。这似乎是相关的,但唯一的代码更改是替换批处理更新方法的实现。

WORKING SOLUTION PROJECT PACKAGES:

<?xml version="1.0" encoding="utf-8"?>
<packages>
  <package id="Antlr" version="3.5.0.2" targetFramework="net45" />
  <package id="Candor.Core" version="1.4.1.0" targetFramework="net451" />
  <package id="Candor.jQuery.AutoAsync" version="3.5.0.40210" targetFramework="net451" />
  <package id="Candor.Security" version="2.4.0.0" targetFramework="net451" />
  <package id="Candor.Security.AzureStorageProvider" version="2.3.2.0" targetFramework="net451" />
  <package id="Candor.Web.Mvc" version="1.0.3.0" targetFramework="net451" />
  <package id="Candor.Web.Mvc.ErrorHandler" version="1.0.0.0" targetFramework="net45" />
  <package id="Candor.Web.Mvc.Security" version="2.1.0.0" targetFramework="net45" />
  <package id="Candor.WindowsAzure" version="1.2.10.0" targetFramework="net451" />
  <package id="Candor.WindowsAzure.Logging.Common" version="1.1.1.0" targetFramework="net451" />
  <package id="Common.Logging" version="2.2.0" targetFramework="net451" />
  <package id="Common.Logging.Core" version="2.2.0" targetFramework="net451" />
  <package id="form2js" version="1.0.0.30224" targetFramework="net45" />
  <package id="jQuery" version="2.0.3" targetFramework="net45" />
  <package id="jQuery.UI.Combined" version="1.10.3" targetFramework="net45" />
  <package id="jQuery.Validation" version="1.11.1" targetFramework="net45" />
  <package id="MarkdownSharp" version="1.13.0.0" targetFramework="net451" />
  <package id="Microsoft.AspNet.Mvc" version="5.0.0" targetFramework="net45" />
  <package id="Microsoft.AspNet.Razor" version="3.0.0" targetFramework="net45" />
  <package id="Microsoft.AspNet.Web.Optimization" version="1.1.2" targetFramework="net45" />
  <package id="Microsoft.AspNet.WebApi" version="5.0.0" targetFramework="net45" />
  <package id="Microsoft.AspNet.WebApi.Client" version="5.0.0" targetFramework="net45" />
  <package id="Microsoft.AspNet.WebApi.Core" version="5.0.0" targetFramework="net45" />
  <package id="Microsoft.AspNet.WebApi.HelpPage" version="5.0.0" targetFramework="net45" />
  <package id="Microsoft.AspNet.WebApi.OData" version="5.0.0" targetFramework="net45" />
  <package id="Microsoft.AspNet.WebApi.WebHost" version="5.0.0" targetFramework="net45" />
  <package id="Microsoft.AspNet.WebPages" version="3.0.0" targetFramework="net45" />
  <package id="Microsoft.AspNet.WebPages.Data" version="3.0.0" targetFramework="net45" />
  <package id="Microsoft.AspNet.WebPages.WebData" version="3.0.0" targetFramework="net45" />
  <package id="Microsoft.Data.Edm" version="5.6.0" targetFramework="net45" />
  <package id="Microsoft.Data.OData" version="5.6.0" targetFramework="net45" />
  <package id="Microsoft.jQuery.Unobtrusive.Ajax" version="3.0.0" targetFramework="net45" />
  <package id="Microsoft.jQuery.Unobtrusive.Validation" version="3.0.0" targetFramework="net45" />
  <package id="Microsoft.Web.Infrastructure" version="1.0.0.0" targetFramework="net45" />
  <package id="Microsoft.WindowsAzure.ConfigurationManager" version="2.0.1.0" targetFramework="net45" />
  <package id="Modernizr" version="2.7.1" targetFramework="net45" />
  <package id="Newtonsoft.Json" version="5.0.8" targetFramework="net45" />
  <package id="SlidesJS" version="3.0.4" targetFramework="net451" />
  <package id="System.Spatial" version="5.6.0" targetFramework="net45" />
  <package id="T4MVC" version="3.7.4" targetFramework="net45" />
  <package id="T4MVCExtensions" version="3.7.4" targetFramework="net45" />
  <package id="WebActivatorEx" version="2.0.4" targetFramework="net45" />
  <package id="WebGrease" version="1.6.0" targetFramework="net451" />
  <package id="WindowsAzure.Storage" version="2.1.0.3" targetFramework="net45" />
</packages>

我试着把它部署成一个网站,只是想看看有什么不同。表连接字符串在appSettings中,从早期尝试解决时间问题,所以尝试网站部署选项(不是云web角色)是有意义的。

这个尝试的错误是

[FileNotFoundException: Could not load file or assembly 'Microsoft.WindowsAzure.ServiceRuntime, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35' or one of its dependencies. The system cannot find the file specified.]
[FileNotFoundException: Could not load file or assembly 'Microsoft.WindowsAzure.ServiceRuntime, Version=2.2.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35' or one of its dependencies. The system cannot find the file specified.]
   Candor.WindowsAzure.Logging.Common.Table.CloudTableLogger.WriteInternal(LogLevel level, Object message, Exception exception) +0
   Common.Logging.Factory.AbstractLogger.Info(Object message) in c:_osscommon-loggingsrcCommon.Logging.CoreLoggingFactoryAbstractLogger.cs:504
   Candor.Configuration.Provider.ProviderCollection`1.SetActiveProvider(T provider) in c:Usersmicha_000DocumentsGitHubcandor-commonCandorConfigurationProviderProviderCollection.cs:166
   Candor.Configuration.Provider.ProviderResolver`1.AppendActive(T provider) in c:Usersmicha_000DocumentsGitHubcandor-commonCandorConfigurationProviderProviderResolver.cs:75

这很奇怪,因为现在部署到云上的另一个工作解决方案web角色将该引用设置为CopyLocal=false。但是当我在这个不工作的解决方案中将其设置为true时,它开始在网站部署中工作。

接下来,我重新部署了云web角色,将这个组件设置为CopyLocal=True,现在它可以工作了。我不知道为什么这是需要在一个项目部署,而不是其他,而两个项目都要求其他azure组件是CopyLocal=true。

关于启动速度还有一个挥之不去的问题,但如果我不解决这个问题,我将把它留给另一个问题。由于某些原因,这个较小的项目在启动后进入繁忙/回收循环,但页面会不时加载。这很奇怪,因为它在启动时初始化的依赖较少,也就是说,实例化的提供程序每个只写一个日志条目。

直接指向问题是- CloudConfigurationManager。GetSetting将从云项目设置中读取给定的配置键,否则将返回到实际的项目应用程序或Web配置。所以如果你确保它存在于其中一个地方,它应该可以正常工作。当您确认它在本地工作时,即使在部署之后,它也应该以完全相同的方式工作。

另一种可能发生的情况是,当您为本地和云部署环境拥有多个配置文件时,该配置可能从您用于部署到云的云配置文件中丢失。

在我的例子中,我使用SlowCheetah (NuGet包)来转换App.config文件。在调试中,它没有使用转换。使用"root"配置文件中的Debug设置解决了我的问题。

最新更新