Outlook加载项的WPF形式中使用的Newtonsoft JSON未找到应用程序配置



我已经为Outlook 2010-2016创建了一个使用Visual Studio 2013的Outlook加载项。Outlook加载项包含2个使用REST API并进行HTTP REST调用的WPF表单。结果是JSON,将与Newtonsoft JSON进行应对。

在调试模式下,一切正常。一旦我使用Wix创建设置工具并安装加载项,我就会出现JSON对象不再被估算化的问题。原因是加载项找不到配置文件。我发现Outlook在Office Outlook程序路径中寻找Outlook.exe.config。但这不是我想要的,因为我不想对可能影响其他应用程序的中央配置文件进行任何更改。

弄清楚了这一点后,我发现了这个整洁的小代码段,以更改加载项的启动时的配置文件:

 using System;
using System.Configuration;
using System.Linq;
using System.Reflection;
public abstract class AppConfig : IDisposable
{
    public static AppConfig Change(string path)
    {
        return new ChangeAppConfig(path);
    }
    public abstract void Dispose();
    private class ChangeAppConfig : AppConfig
    {
        private readonly string oldConfig =
            AppDomain.CurrentDomain.GetData("APP_CONFIG_FILE").ToString();
        private bool disposedValue;
        public ChangeAppConfig(string path)
        {
            AppDomain.CurrentDomain.SetData("APP_CONFIG_FILE", path);
            ResetConfigMechanism();
        }
        public override void Dispose()
        {
            if (!disposedValue)
            {
                AppDomain.CurrentDomain.SetData("APP_CONFIG_FILE", oldConfig);
                ResetConfigMechanism();

                disposedValue = true;
            }
            GC.SuppressFinalize(this);
        }
        private static void ResetConfigMechanism()
        {
            typeof(ConfigurationManager)
                .GetField("s_initState", BindingFlags.NonPublic |
                                         BindingFlags.Static)
                .SetValue(null, 0);
            typeof(ConfigurationManager)
                .GetField("s_configSystem", BindingFlags.NonPublic |
                                            BindingFlags.Static)
                .SetValue(null, null);
            typeof(ConfigurationManager)
                .Assembly.GetTypes()
                .Where(x => x.FullName ==
                            "System.Configuration.ClientConfigPaths")
                .First()
                .GetField("s_current", BindingFlags.NonPublic |
                                       BindingFlags.Static)
                .SetValue(null, null);
        }
    }
}

将应用程序配置更改为正确的路径后,我可以通过system.configuration.confgurationmanager读取所有设置(confgurationManager)。

,但仍然...试图将JSON验证为对象时,我会收到以下错误:

system.io.io.fileleloadexception:无法加载文件或组装 'newtonsoft.json,版本= 4.5.0.0,文化=中性, publicKeyToken = 30AD4FE6B2A6AEED'或其依赖性之一。这 位于汇编的清单定义与组件不匹配 参考。(Hresult的例外:0x80131040)文件名: 'newtonsoft.json,版本= 4.5.0.0,文化=中性, publicKeyToken = 30ad4fe6b2a6aeed'at system.net.http.formatting.jsonmediatypeformatter..ctor()at system.net.http.formatting.MediatypeFormatterCollection.CreatedEdeFaultFormatters() 在 xxxxxxxxxxxxxxxxxx。 任务)

=== pre-bind状态信息=== log:displayName = newtonsoft.json,版本= 4.5.0.0,culture =中性,publicKeyToken = 30AD4FE6B2A6AEED (完全指定)log:appbase = file:///c:/program files/xxxxxxxxxxx/xxxxxxxxx/ 日志:初始privatePath = null调用组件: system.net.http.formatting,版本= 4.0.0.0,文化=中性, publicKeyToken = 31BF3856AD364E35。 === log:此绑定在默认加载上下文中开始。日志:找不到应用程序配置文件。日志:使用主机配置文件:日志: 使用机器配置文件 C: Windows Microsoft.net Framework V4.0.30319 config Machine.config。 日志:post-policy参考:newtonsoft.json,版本= 4.5.0.0, 文化=中性,publicKeyToken = 30AD4FE6B2A6AEED日志:尝试 下载新URL文件:///C:/Program 文件/xxxxxx/newtonsoft.json.dll。WRN:比较集会名称 导致不匹配:主要版本错误:无法完成设置 组装(HR = 0x80131040)。探测终止。

这就是我的app.config文件的样子:

<?xml version="1.0" encoding="utf-8"?>>
<configuration>
  <appSettings>
    <add key="ApiUrl" value="http://localhost:56610/api" />
  </appSettings>
  <runtime>
    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
      <dependentAssembly>
        <assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
        <bindingRedirect oldVersion="0.0.0.0-9.0.0.0" newVersion="9.0.0.0" />
      </dependentAssembly>
    </assemblyBinding>
  </runtime>
</configuration>

有人知道为什么Newtonsoft JSON的配置不起作用,为什么我提供的配置不使用?

非常感谢您的任何帮助。

我找到了解决问题的解决方法。我的最初代码如下:

        public DomainUser FindUserBySecurityIdentifier(SecurityIdentifier securityIdentifier)
    {
        var domainUser = new DomainUser(securityIdentifier.ToString());
        string domainUserJson = Newtonsoft.Json.JsonConvert.SerializeObject(domainUser);
        HttpContent content = new StringContent(domainUserJson);
        content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/json");
        Exception exception = null;
        var item = DomainUser.EMPTY;
        var endpointUrl = ConstructEndpointUrl("api/FindUserBySecurityIdentifier");
        if (!string.IsNullOrWhiteSpace(endpointUrl))
        {
            Task postLink = HttpClient.PostAsync(endpointUrl, content).ContinueWith(task =>
            {
                if (task.Status == TaskStatus.RanToCompletion)
                {
                    var response = task.Result;
                    if (response.IsSuccessStatusCode)
                    {
                        // The error occured at this line
                        item = response.Content.ReadAsAsync<DomainUser>().Result;
                    }
                    else
                    {
                        exception = new Exception(response.ToString());
                    }
                }
                else
                {
                    exception = new Exception("The http request to the server did not run to completion. Please contact the administrator");
                }
            });
            postLink.Wait();
        }
        if (exception != null)
        {
            throw exception;
        }
        return item;
    }

在我更改代码之后,它最终起作用

        public DomainUser FindUserBySecurityIdentifier(SecurityIdentifier securityIdentifier)
    {
        var domainUser = new DomainUser(securityIdentifier.ToString());
        string domainUserJson = Newtonsoft.Json.JsonConvert.SerializeObject(domainUser);
        HttpContent content = new StringContent(domainUserJson);
        content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("application/json");
        Exception exception = null;
        var item = DomainUser.EMPTY;
        var endpointUrl = ConstructEndpointUrl("api/FindUserBySecurityIdentifier");
        if (!string.IsNullOrWhiteSpace(endpointUrl))
        {
            Task postLink = HttpClient.PostAsync(endpointUrl, content).ContinueWith(task =>
            {
                if (task.Status == TaskStatus.RanToCompletion)
                {
                    var response = task.Result;
                    if (response.IsSuccessStatusCode)
                    {
                        // after I read the result into a string first and deserialized it with JsonConvert.DeserializeObject it worked
                        var objectAsString = response.Content.ReadAsStringAsync().Result;
                        item = JsonConvert.DeserializeObject<DomainUser>(objectAsString);
                    }
                    else
                    {
                        exception = new Exception(response.ToString());
                    }
                }
                else
                {
                    exception = new Exception("The http request to the server did not run to completion. Please contact the administrator");
                }
            });
            postLink.Wait();
        }
        if (exception != null)
        {
            throw exception;
        }
        return item;
    }

相关内容

  • 没有找到相关文章

最新更新