2017-02-19 4 views
8

При использовании ServiceHost.AddServiceEndpoint добавить пользовательские ProtoEndpointBehavior я получаю следующее исключение:Кнопка AddServiceEndpoint бросает значение null?

System.ArgumentNullException: Значение не может быть пустым. Имя параметра: ключ на System.Collections.Generic.Dictionary 2.FindEntry(TKey key) at System.Collections.Generic.Dictionary 2.ContainsKey (клавиша TKey) в System.ServiceModel.ServiceHostBase.ImplementedContractsContractResolver.ResolveContract (String contractName) в System.ServiceModel.ServiceHostBase.ServiceAndBehaviorsContractResolver.ResolveContract (String contractName) при System.ServiceModel.Description.ConfigLoader.LookupContractForStandardEndpoint (String contractName, String ServiceName) на System.ServiceModel.Description.ConfigLoader.LookupContract (String contractName, String ServiceName) на System.ServiceModel.ServiceHostBase.AddServiceEndpoint (ServiceEndpoint endpoi нт) в My.Service.Business.ServiceHandler.StartService (тип ServiceType, Строка Uri, SecureConnectionSettings secureConnectionSettings) в C: \ My \ PRODUKTER \ My Utveckling \ Solution \ My.Service.Business \ ServiceHandler.cs: линии 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> 

Теперь мне нужно добавить его вместо кода.

Что не так?

+0

Какая строка в коде, который вы опубликовали, бросает эту ошибку? – Sparrow

+0

@FeryalBadili Он забрасывается в конечную точку.EndpointBehaviors.Add row. – Banshee

ответ

4

Это 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)); 

Я был в состоянии воспроизвести вашу проблему и этот обходной путь работал для меня.

1

Причина, по которой вы видите исключение, состоит в том, что ServiceEndpoint предположил, что вы используете файл конфигурации. Он пытается восстановить &, разрешая ваш контракт, привязку и адрес, которых нет, потому что вы не используете файл конфигурации.

ServiceEndpoint (см замечания)

Используйте этот конструктор, когда связывание и адрес для конечной точки являются , представленной в конфигурации.

Есть несколько способов 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 программно вам необходимо определить некоторые из следующих действий:

  • ContractDescription
  • OperationDescription
  • MessageDescription
  • 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(); 
     } 
    } 
} 

К сожалению, я не мог прилагается изображение «что-то не так с Imgur» но это работает на моем веб-браузере. Хотя я не тестировал использование клиентского приложения, но, думаю, вы уже близко к решению.

Совет: Не смешивайте конфигурационный файл и код, потому что его очень сложно поддерживать. «Что вы, наверное, знали» Удачи :)

+0

Спасибо! Да, CodeFuller, похоже, решает проблему, но я все еще проверяю, действительно ли она решена. – Banshee

Смежные вопросы