Чтение элементов поведения WCF из конфигурационного файла программным путем при предоставлении собственной службы

У меня есть эта конфигурация в моем app.config:

    </binding>
  </basicHttpBinding>
</bindings>



<behaviors>
  <serviceBehaviors>
    <behavior name="myBehavior">
      <serviceMetadata httpGetEnabled="true"/>
      <serviceDebug includeExceptionDetailInFaults="true"/>
    </behavior>
  </serviceBehaviors>
</behaviors>

I want to expose this service programmatically from my desktop app:

Я определяю экземпляр хоста:

ServiceHost host = new ServiceHost(typeof(MyType), new Uri("http://" + hostName + ":" + port + "/MyName"));

Затем я добавляю конечную точку с ее привязкой:

var binding = new BasicHttpBinding("myBinding");
host.AddServiceEndpoint(typeof(IMyInterface), binding, "MyName");

Теперь я хочу заменить приведенный ниже код кодом, который считывает поведение с именем myBehavior из файла конфигурации, а не жестко задает параметры поведения.

ServiceMetadataBehavior smb = new ServiceMetadataBehavior() { HttpGetEnabled = true };    
host.Description.Behaviors.Add(smb);   
// Enable exeption details
ServiceDebugBehavior sdb = host.Description.Behaviors.Find<ServiceDebugBehavior>();
sdb.IncludeExceptionDetailInFaults = true;

Затем я могу открыть host.

host.Open();

* ИЗМЕНИТЬ *

Настройка служб с помощью файлов конфигурации

Вам не нужен этот способ, вы должны сделать так, чтобы хост автоматически брал свои настройки из файла конфигурации, а не отдавал их вручную, читайте эта статья (Настройка служб с помощью файлов конфигурации), она вам поможет, я разместил свою службу в одной строке на C# и несколько в config.

Это вторая статья о (настройке служб WCF в коде), моей вина в том, что я пытался смешать два пути!

Я добавлю это как ответ.


person Sawan    schedule 25.12.2012    source источник
comment
Есть законные причины не использовать файл конфигурации, т. е. получение адресов и тому подобного из внешнего источника.   -  person Craig Brett    schedule 20.05.2014


Ответы (3)


Во-первых, вам нужно открыть файл конфигурации, используя либо

var config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);

or

var map = new ExeConfigurationFileMap();
map.ExeConfigFilename = "app.config";
var config = ConfigurationManager.OpenMappedExeConfiguration(map, ConfigurationUserLevel.None);

Затем вы читаете поведение:

var bindings = BindingsSection.GetSection(config);
var group = ServiceModelSectionGroup.GetSectionGroup(config);
foreach (var behavior in group.Behaviors.ServiceBehaviors)
{
    Console.WriteLine ("BEHAVIOR: {0}", behavior);
}

Обратите внимание, что они относятся к типу System.ServiceModel.Configuration.ServiceBehaviorElement, так что это еще не совсем то, что вам нужно.

Если вы не возражаете против использования частных API, вы можете вызвать защищенный метод BehaviorExtensionElement.CreateBehavior() через отражение:

foreach (BehaviorExtensionElement bxe in behavior)
{
    var createBeh = typeof(BehaviorExtensionElement).GetMethod(
        "CreateBehavior", BindingFlags.Instance | BindingFlags.NonPublic);
    IServiceBehavior b = (IServiceBehavior)createBeh.Invoke(bxe, new object[0]);
    Console.WriteLine("BEHAVIOR: {0}", b);
    host.Description.Behaviors.Add (b);
}
person Martin Baulig    schedule 25.12.2012

Настройка служб с помощью файлов конфигурации

Вам не нужен этот способ, вы должны сделать так, чтобы хост автоматически брал свои настройки из файла конфигурации, а не отдавал их вручную, читайте эта статья (Настройка служб с помощью файлов конфигурации), она вам поможет, я разместил свою службу в одной строке на C# и несколько в config.

Это вторая статья о (настройке служб WCF в коде), моей вина в том, что я пытался смешать два пути!

person Sawan    schedule 29.12.2012
comment
Если вы не хотите использовать файлы конфигурации по умолчанию - person Random; 11.12.2014

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

var behaviorSection = ConfigurationManager.GetSection("system.serviceModel/behaviors") as BehaviorsSection;
if (behaviorSection != null)
{
                // for each behavior, check for client and server certificates
    foreach (EndpointBehaviorElement behavior in behaviorSection.EndpointBehaviors)
    {
        foreach (PropertyInformation pi in behavior.ElementInformation.Properties)
        {
            if (pi.Type == typeof(ClientCredentialsElement))
            {
                var clientCredentials = pi.Value as ClientCredentialsElement;
                var clientCert = clientCredentials.ClientCertificate;
                            // TODO: Add code...
            }
        }
    }
}

ConfigurationManager.Open...Configuration() плохо работает с веб-проектами, поэтому вручную получить раздел и выполнить кастинг проще.

Если вы действительно настаиваете на том, чтобы System.ServiceModel читал конфигурацию за вас, можно сделать что-то вроде этого:

ExeConfigurationFileMap map = new ExeConfigurationFileMap();
map.ExeConfigFilename = System.IO.Path.Combine(HttpContext.Current.Server.MapPath("~"), "web.config"); // the root web.config  
Configuration config = ConfigurationManager.OpenMappedExeConfiguration(map, ConfigurationUserLevel.None);
var group = ServiceModelSectionGroup.GetSectionGroup(config);

foreach (EndpointBehaviorElement item in group.Behaviors.EndpointBehaviors)
{
    // TODO: add code...
}

Второй метод использует HttpContext.Current, и, как мы все знаем, HttpContext.Current ужасен при выполнении модульных тестов.

person Tikall    schedule 22.09.2015