AddServiceEndpoint 抛出键为空?
AddServiceEndpoint throws key is null?
使用 ServiceHost.AddServiceEndpoint 添加自定义 ProtoEndpointBehavior 时出现以下异常:
System.ArgumentNullException: Value cannot be null. Parameter name:
key at System.Collections.Generic.Dictionary2.FindEntry(TKey key)
at System.Collections.Generic.Dictionary
2.ContainsKey(TKey key) at
System.ServiceModel.ServiceHostBase.ImplementedContractsContractResolver.ResolveContract(String
contractName) at
System.ServiceModel.ServiceHostBase.ServiceAndBehaviorsContractResolver.ResolveContract(String
contractName) at
System.ServiceModel.Description.ConfigLoader.LookupContractForStandardEndpoint(String
contractName, String serviceName) at
System.ServiceModel.Description.ConfigLoader.LookupContract(String
contractName, String serviceName) at
System.ServiceModel.ServiceHostBase.AddServiceEndpoint(ServiceEndpoint
endpoint) at
My.Service.Business.ServiceHandler.StartService(Type serviceType,
String uri, SecureConnectionSettings secureConnectionSettings) in
C:\My\Produkter\My
Utveckling\Solution\My.Service.Business\ServiceHandler.cs:line 150
代码如下所示:
ServiceHost serviceHost = null;
Console.WriteLine("Creating service " + serviceType.FullName);
serviceHost = new MyServiceHost(serviceType, new Uri(uri));
var endPointAddress = "";
HttpBindingBase binding = null;
if (secureConnectionSettings != null && secureConnectionSettings.Enabled)
{
Console.WriteLine("Setting certificates");
X509Store store = new X509Store(secureConnectionSettings.CertificateStore, secureConnectionSettings.CertificateLocation);
store.Open(OpenFlags.ReadOnly);
X509Certificate2Collection certs = store.Certificates.Find(X509FindType.FindByThumbprint, secureConnectionSettings.Thumbprint, true);
store.Close();
if (certs.Count > 0)
serviceHost.Credentials.ServiceCertificate.SetCertificate(secureConnectionSettings.CertificateLocation,
secureConnectionSettings.CertificateStore,
X509FindType.FindByThumbprint,
secureConnectionSettings.Thumbprint);
else
throw new Exception("Could not finde certificate with thumbprint " + secureConnectionSettings.Thumbprint);
endPointAddress = uri + "/BinaryHttpsProto";
binding = CreateNetHttpsBinding(secureConnectionSettings);
}
else
{
endPointAddress = uri + "/BinaryHttpProto";
binding = CreateNetHttpBinding();
}
var endpoint = new System.ServiceModel.Description.ServiceEndpoint(new System.ServiceModel.Description.ContractDescription(typeof(IMyClientService).FullName),
binding,
new EndpointAddress(endPointAddress));
endpoint.EndpointBehaviors.Add(new ProtoBuf.ServiceModel.ProtoEndpointBehavior());
serviceHost.AddServiceEndpoint(endpoint);
Console.WriteLine("Starting service...");
serviceHost.Open();
Console.WriteLine("Service started successfully (" + uri + ")");
return serviceHost;
我过去常常在配置文件中这样设置:
<endpointBehaviors>
<behavior name="protoEndpointBehavior">
<protobuf />
</behavior>
</endpointBehaviors>
现在我需要在代码中添加它。
怎么了?
这是一个 known bug 并且有解决方法。
获取 ContractDescription 实例时,使用静态方法 ContractDescription.GetContract(Type) 而不是直接 ContractDescription() 构造函数:
var endpoint = new System.ServiceModel.Description.ServiceEndpoint(System.ServiceModel.Description.ContractDescription.GetContract(typeof(IMyClientService)),
binding,
new EndpointAddress(endPointAddress));
我能够重现你的问题,这个解决方法对我有用。
您看到异常的原因是因为 ServiceEndpoint
假定您使用配置文件。它正在尝试检索并解析您不存在的合同、绑定和地址,因为您没有使用配置文件。
ServiceEndpoint(见备注)
Use this constructor when the binding and address for the endpoint are
provided in configuration.
create or retrieve a ContractDescription对象有多种方法:
var contractUsingName = new ContractDescription("IProtoBufService");
var contractUsingNameWithNameSpace = new ContractDescription("IProtoBufService", "http://www.tempuri.org");
var contractUsingContractType = ContractDescription.GetContract(typeof(IProtoBufService));
var contractUsingContractTypeAndObjectImp = ContractDescription.GetContract(typeof(IProtoBufService), ProtoBufService);
var contractUsingContractTypeAndObjectType = ContractDescription.GetContract(typeof(IProtoBufService), typeof(ProtoBufService));
如果您真的坚持以编程方式创建 ContractDescription
您需要定义以下一些内容:
- 合同描述
- 操作说明
- 消息描述
- OperationBehaviorAttribute
- 和其他东西...
或者你可以按照这个 blog 作为踢球者。
你试过CodeFuller的回答了吗?他的回答可以让你的生活更轻松。我进行了快速检查,它起作用了。
class Program
{
static void Main()
{
var baseAddress = new Uri("http://localhost:8080/ProtoBuf");
using (var serviceHost = new ServiceHost(typeof(ProtoBufService), baseAddress))
{
var endpoint = new ServiceEndpoint(ContractDescription.GetContract(typeof(IProtoBufService)),
new NetHttpBinding(),
new EndpointAddress(baseAddress));
endpoint.EndpointBehaviors.Add(new ProtoEndpointBehavior());
serviceHost.AddServiceEndpoint(endpoint);
serviceHost.Open();
Console.ReadKey();
}
}
}
不幸的是,我无法附上图片 "something's wrong with imgur" 但它可以在我的网络浏览器上运行。虽然我还没有使用客户端应用程序进行测试,但我想你已经接近解决方案了。
提示:不要混用配置文件和代码,因为这样很难维护。 "Which you probably knew"祝你好运:)
使用 ServiceHost.AddServiceEndpoint 添加自定义 ProtoEndpointBehavior 时出现以下异常:
System.ArgumentNullException: Value cannot be null. Parameter name: key at System.Collections.Generic.Dictionary
2.FindEntry(TKey key) at System.Collections.Generic.Dictionary
2.ContainsKey(TKey key) at System.ServiceModel.ServiceHostBase.ImplementedContractsContractResolver.ResolveContract(String contractName) at System.ServiceModel.ServiceHostBase.ServiceAndBehaviorsContractResolver.ResolveContract(String contractName) at System.ServiceModel.Description.ConfigLoader.LookupContractForStandardEndpoint(String contractName, String serviceName) at System.ServiceModel.Description.ConfigLoader.LookupContract(String contractName, String serviceName) at System.ServiceModel.ServiceHostBase.AddServiceEndpoint(ServiceEndpoint endpoint) at My.Service.Business.ServiceHandler.StartService(Type serviceType, String uri, SecureConnectionSettings secureConnectionSettings) in C:\My\Produkter\My Utveckling\Solution\My.Service.Business\ServiceHandler.cs:line 150
代码如下所示:
ServiceHost serviceHost = null;
Console.WriteLine("Creating service " + serviceType.FullName);
serviceHost = new MyServiceHost(serviceType, new Uri(uri));
var endPointAddress = "";
HttpBindingBase binding = null;
if (secureConnectionSettings != null && secureConnectionSettings.Enabled)
{
Console.WriteLine("Setting certificates");
X509Store store = new X509Store(secureConnectionSettings.CertificateStore, secureConnectionSettings.CertificateLocation);
store.Open(OpenFlags.ReadOnly);
X509Certificate2Collection certs = store.Certificates.Find(X509FindType.FindByThumbprint, secureConnectionSettings.Thumbprint, true);
store.Close();
if (certs.Count > 0)
serviceHost.Credentials.ServiceCertificate.SetCertificate(secureConnectionSettings.CertificateLocation,
secureConnectionSettings.CertificateStore,
X509FindType.FindByThumbprint,
secureConnectionSettings.Thumbprint);
else
throw new Exception("Could not finde certificate with thumbprint " + secureConnectionSettings.Thumbprint);
endPointAddress = uri + "/BinaryHttpsProto";
binding = CreateNetHttpsBinding(secureConnectionSettings);
}
else
{
endPointAddress = uri + "/BinaryHttpProto";
binding = CreateNetHttpBinding();
}
var endpoint = new System.ServiceModel.Description.ServiceEndpoint(new System.ServiceModel.Description.ContractDescription(typeof(IMyClientService).FullName),
binding,
new EndpointAddress(endPointAddress));
endpoint.EndpointBehaviors.Add(new ProtoBuf.ServiceModel.ProtoEndpointBehavior());
serviceHost.AddServiceEndpoint(endpoint);
Console.WriteLine("Starting service...");
serviceHost.Open();
Console.WriteLine("Service started successfully (" + uri + ")");
return serviceHost;
我过去常常在配置文件中这样设置:
<endpointBehaviors>
<behavior name="protoEndpointBehavior">
<protobuf />
</behavior>
</endpointBehaviors>
现在我需要在代码中添加它。
怎么了?
这是一个 known bug 并且有解决方法。
获取 ContractDescription 实例时,使用静态方法 ContractDescription.GetContract(Type) 而不是直接 ContractDescription() 构造函数:
var endpoint = new System.ServiceModel.Description.ServiceEndpoint(System.ServiceModel.Description.ContractDescription.GetContract(typeof(IMyClientService)),
binding,
new EndpointAddress(endPointAddress));
我能够重现你的问题,这个解决方法对我有用。
您看到异常的原因是因为 ServiceEndpoint
假定您使用配置文件。它正在尝试检索并解析您不存在的合同、绑定和地址,因为您没有使用配置文件。
ServiceEndpoint(见备注)
Use this constructor when the binding and address for the endpoint are provided in configuration.
create or retrieve a ContractDescription对象有多种方法:
var contractUsingName = new ContractDescription("IProtoBufService");
var contractUsingNameWithNameSpace = new ContractDescription("IProtoBufService", "http://www.tempuri.org");
var contractUsingContractType = ContractDescription.GetContract(typeof(IProtoBufService));
var contractUsingContractTypeAndObjectImp = ContractDescription.GetContract(typeof(IProtoBufService), ProtoBufService);
var contractUsingContractTypeAndObjectType = ContractDescription.GetContract(typeof(IProtoBufService), typeof(ProtoBufService));
如果您真的坚持以编程方式创建 ContractDescription
您需要定义以下一些内容:
- 合同描述
- 操作说明
- 消息描述
- OperationBehaviorAttribute
- 和其他东西...
或者你可以按照这个 blog 作为踢球者。
你试过CodeFuller的回答了吗?他的回答可以让你的生活更轻松。我进行了快速检查,它起作用了。
class Program
{
static void Main()
{
var baseAddress = new Uri("http://localhost:8080/ProtoBuf");
using (var serviceHost = new ServiceHost(typeof(ProtoBufService), baseAddress))
{
var endpoint = new ServiceEndpoint(ContractDescription.GetContract(typeof(IProtoBufService)),
new NetHttpBinding(),
new EndpointAddress(baseAddress));
endpoint.EndpointBehaviors.Add(new ProtoEndpointBehavior());
serviceHost.AddServiceEndpoint(endpoint);
serviceHost.Open();
Console.ReadKey();
}
}
}
不幸的是,我无法附上图片 "something's wrong with imgur" 但它可以在我的网络浏览器上运行。虽然我还没有使用客户端应用程序进行测试,但我想你已经接近解决方案了。
提示:不要混用配置文件和代码,因为这样很难维护。 "Which you probably knew"祝你好运:)