Как добавить настраиваемый HTTP-заголовок для каждого вызова WCF?

У меня есть служба WCF, размещенная в службе Windows. Клиенты, использующие эту службу, должны передавать идентификатор каждый раз, когда они вызывают методы службы (поскольку этот идентификатор важен для того, что должен делать вызываемый метод). Я подумал, что это хорошая идея, чтобы как-то поместить этот идентификатор в информацию заголовка WCF.

Если это хорошая идея, как я могу автоматически добавить идентификатор в информацию заголовка. Другими словами, всякий раз, когда пользователь вызывает метод WCF, идентификатор должен автоматически добавляться в заголовок.

ОБНОВЛЕНИЕ: Клиенты, использующие службу WCF, являются приложениями Windows и приложением Windows Mobile (с использованием Compact Framework).

Преимущество этого заключается в том, что оно применяется к каждому вызову.

Создайте class, который реализует IClientMessageInspector . В методе BeforeSendRequest добавьте свой настраиваемый заголовок в исходящее сообщение. Это может выглядеть примерно так:

public object BeforeSendRequest(ref System.ServiceModel.Channels.Message request, System.ServiceModel.IClientChannel channel) { HttpRequestMessageProperty httpRequestMessage; object httpRequestMessageObject; if (request.Properties.TryGetValue(HttpRequestMessageProperty.Name, out httpRequestMessageObject)) { httpRequestMessage = httpRequestMessageObject as HttpRequestMessageProperty; if (string.IsNullOrEmpty(httpRequestMessage.Headers[USER_AGENT_HTTP_HEADER])) { httpRequestMessage.Headers[USER_AGENT_HTTP_HEADER] = this.m_userAgent; } } else { httpRequestMessage = new HttpRequestMessageProperty(); httpRequestMessage.Headers.Add(USER_AGENT_HTTP_HEADER, this.m_userAgent); request.Properties.Add(HttpRequestMessageProperty.Name, httpRequestMessage); } return null; } 

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

Вот отличный пример того, как добавить заголовок пользовательского агента HTTP ко всем сообщениям запроса. Я использую это в нескольких моих клиентах. Вы также можете сделать то же самое на стороне обслуживания, выполнив IDispatchMessageInspector .

Это то, что вы имели в виду?

Обновление: я нашел этот список функций WCF, поддерживаемых компактной картой. Я считаю, что инспекторы сообщений classифицируются как «Расширение канала», которые, согласно этому сообщению, поддерживаются компактной инфраструктурой.

Вы добавляете его к вызову, используя:

 using (OperationContextScope scope = new OperationContextScope((IContextChannel)channel)) { MessageHeader header = new MessageHeader("secret message"); var untyped = header.GetUntypedHeader("Identity", "http://www.my-website.com"); OperationContext.Current.OutgoingMessageHeaders.Add(untyped); // now make the WCF call within this using block } 

И затем, на стороне сервера вы его захватите, используя:

 MessageHeaders headers = OperationContext.Current.IncomingMessageHeaders; string identity = headers.GetHeader("Identity", "http://www.my-website.com"); 

Если вы просто хотите добавить один и тот же заголовок ко всем запросам службы, вы можете сделать это без какой-либо кодировки!
Просто добавьте узел заголовков с требуемыми заголовками под узлом конечной точки в файле конфигурации клиента

    Value   

Вот еще одно полезное решение для ручного добавления пользовательских заголовков HTTP в ваш клиентский запрос WCF с использованием ChannelFactory в качестве прокси. Это нужно было бы сделать для каждого запроса, но в качестве простой демонстрации достаточно, если вам просто нужно будет протестировать ваш прокси-сервер для подготовки к платформам .NET.

 // create channel factory / proxy ... using (OperationContextScope scope = new OperationContextScope(proxy)) { OperationContext.Current.OutgoingMessageProperties[HttpRequestMessageProperty.Name] = new HttpRequestMessageProperty() { Headers = { { "MyCustomHeader", Environment.UserName }, { HttpRequestHeader.UserAgent, "My Custom Agent"} } }; // perform proxy operations... } 

Это похоже на ответ NimsDotNet, но показывает, как это сделать программно.

Просто добавьте заголовок к привязке

 var cl = new MyServiceClient(); var eab = new EndpointAddressBuilder(cl.Endpoint.Address); eab.Headers.Add( AddressHeader.CreateAddressHeader("ClientIdentification", // Header Name string.Empty, // Namespace "JabberwockyClient")); // Header Value cl.Endpoint.Address = eab.ToEndpointAddress(); 
 var endpoint = new EndpointAddress(new Uri(RemoteAddress), new[] { AddressHeader.CreateAddressHeader("APIKey", "", "bda11d91-7ade-4da1-855d-24adfe39d174") }); 

Вы можете указать пользовательские заголовки в MessageContract .

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

Контекстные привязки в .NET 3.5 могут быть именно тем, что вы ищете. Есть три варианта: BasicHttpContextBinding, NetTcpContextBinding и WSHttpContextBinding. Контекстный протокол в основном передает пары ключ-значение в заголовке сообщения. Посмотрите статью « Управление государством с долговременными службами» в журнале MSDN.

Если я правильно понимаю ваше требование, простой ответ таков: вы не можете.

Это связано с тем, что клиент службы WCF может генерироваться любой третьей стороной, использующей вашу службу.

Если вы контролируете клиентов своей службы, вы можете создать базовый клиентский class, который добавит желаемый заголовок и наследует поведение на рабочих classах.

Это то, что сработало для меня, адаптировано из « Добавление заголовков HTTP в вызовы WCF»

 // Message inspector used to add the User-Agent HTTP Header to the WCF calls for Server public class AddUserAgentClientMessageInspector : IClientMessageInspector { public object BeforeSendRequest(ref System.ServiceModel.Channels.Message request, IClientChannel channel) { HttpRequestMessageProperty property = new HttpRequestMessageProperty(); var userAgent = "MyUserAgent/1.0.0.0"; if (request.Properties.Count == 0 || request.Properties[HttpRequestMessageProperty.Name] == null) { var property = new HttpRequestMessageProperty(); property.Headers["User-Agent"] = userAgent; request.Properties.Add(HttpRequestMessageProperty.Name, property); } else { ((HttpRequestMessageProperty)request.Properties[HttpRequestMessageProperty.Name]).Headers["User-Agent"] = userAgent; } return null; } public void AfterReceiveReply(ref System.ServiceModel.Channels.Message reply, object correlationState) { } } // Endpoint behavior used to add the User-Agent HTTP Header to WCF calls for Server public class AddUserAgentEndpointBehavior : IEndpointBehavior { public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime) { clientRuntime.MessageInspectors.Add(new AddUserAgentClientMessageInspector()); } public void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters) { } public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher) { } public void Validate(ServiceEndpoint endpoint) { } } 

После объявления этих classов вы можете добавить новое поведение к клиенту WCF следующим образом:

 client.Endpoint.Behaviors.Add(new AddUserAgentEndpointBehavior()); 

Это работает для меня

TestService.ReconstitutionClient _serv = new TestService.TestClient ();

  using (OperationContextScope contextScope = new OperationContextScope(_serv.InnerChannel)) { HttpRequestMessageProperty requestMessage = new HttpRequestMessageProperty(); requestMessage.Headers["apiKey"] = ConfigurationManager.AppSettings["apikey"]; OperationContext.Current.OutgoingMessageProperties[HttpRequestMessageProperty.Name] = requestMessage; _serv.Method(Testarg); } 

Немного поздно, но Юваль Лоуи описывает этот точный сценарий в своей книге и соответствующей библиотеке ServiceModelEx .

В основном он определяет специализации ClientBase и ChannelFactory, которые позволяют указывать значения заголовков, безопасных для типов. Я рекомендую загрузить исходный код и посмотреть classы HeaderClientBase и HeaderChannelFactory.

Джон

Interesting Posts

Разница между int и char в getchar / fgetc и putchar / fputc?

Использование в качестве конкретного типа, соответствующего протоколу AnyObject, не поддерживается

‘printf’ vs. ‘cout’ в C ++

Как отключить или изменить горячую клавишу Windows + S в OneNote

У меня есть PCI-карта с напряжением 3,3 вольта, работающая на 5-вольтном PCI-слоте. Как это возможно?

Запросить XDocument для элементов по имени на любой глубине

Как читать весь stream в std :: string?

Весенняя загрузка добавляет перехватчики http-запросов

Спасение hdd с плохими секторами: dd vs gddrescue

Windows 7 выходит из сна, когда я открываю удаленный рабочий стол

Копирование структуры, содержащей указатели на устройство CUDA

Как настроить log4j с файлом свойств

Настройка облачной библиотеки точек с помощью Visual Studio

Восстановление данных из полного формата в разделе NTFS

В чем разница между параллелизмом, параллелизмом и асинхронными методами?

Давайте будем гением компьютера.