我已经为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;
}