Вот в чем дело:
У меня есть бизнес-запрос на то, чтобы все сообщения WCF имели определенный заголовок для отслеживания и обеспечения безопасности.
В любом случае, я настраиваю реализацию MessageInspector
как на клиенте, так и на сервисе - мы до сих пор контролировали оба конца - и все хорошо работали на стадии прототипа.
Однако сегодня что-то пошло наперекосяк и перестало работать.
Я переделал прототип с нуля, и все работает отлично.Я теряю свои шарики из-за этого весь день.
Соответствующий код выглядит следующим образом:
public class DispatchEndpointBehavior : IEndpointBehavior
{
public void ApplyDispatchBehavior(ServiceEndpoint endpoint,
EndpointDispatcher endpointDispatcher)
{
var mi = new MessageInspector();
endpointDispatcher.DispatchRuntime.MessageInspectors.Add(mi);
}
// ...
}
public class DispatchMessageInspector : IDispatchMessageInspector
{
public object AfterReceiveRequest(ref Message request,
IClientChannel channel,
InstanceContext instanceContext)
{
var index = request.Headers.FindHeader("name", "");
if (index == -1)
throw new MessageSecurityException("...");
var value = request.Headers.GetHeader<Guid>(index);
// do something with the value
return null;
}
// ...
}
public class ClientEndpointBehavior : IClientEndpointBehavior
{
public void ApplyClientBehavior(ServiceEndpoint endpoint,
ClientRuntime clientRuntime)
{
var mi = new ClientSecurityMessageInspector();
clientRuntime.MessageInspectors.Add(mi);
}
// ...
}
public class ClientSecurityMessageInspector : IClientMessageInspector
{
public object BeforeSendRequest(ref Message request,
IClientChannel channel)
{
request.Headers.Add(MessageHeader.CreateHeader("name", "", Guid.NewGuid()));
return null;
}
// ...
}
Вот конфигурация службы:
<system.serviceModel>
<services>
<service behaviorConfiguration="Default" name="[Service Name]">
<endpoint
address=""
binding="basicHttpBinding"
behaviorConfiguration="headerBehavior"
contract="[Service Contract]"/>
<endpoint address="mex" ... />
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="Default">
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true" />
</behavior>
</serviceBehaviors>
<endpointBehaviors>
<behavior name="headerBehavior">
<headerBehavior headerName="token" />
</behavior>
</endpointBehaviors>
</behaviors>
<extensions>
<behaviorExtensions>
<add name="headerBehavior" type="[Implementation Type]" />
</behaviorExtensions>
</extensions>
</system.serviceModel>
Аналогично, конфигурация клиента:
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="[Service name]" ... >
<readerQuotas ... />
<security mode="None">
<transport
clientCredentialType="None"
proxyCredentialType="None"
realm=""/>
<message
clientCredentialType="UserName"
algorithmSuite="Default" />
</security>
</binding>
</basicHttpBinding>
</bindings>
<client>
<endpoint
address="http://.../MyService.svc"
binding="basicHttpBinding"
bindingConfiguration="Default"
contract="[Service Contract]"
name="[Service Name]"
behaviorConfiguration="headerBehavior" />
</client>
<behaviors>
<endpointBehaviors>
<behavior name="headerBehavior">
<headerBehavior
headerName="prosper-security-token"
securityTokenValueService="[Implementation Type]"
securityTokenValueGetterMethodName="[Method Name]" />
</behavior>
</endpointBehaviors>
</behaviors>
<extensions>
<behaviorExtensions>
<add name="headerBehavior" type="[Implementation Type]" />
</behaviorExtensions>
</extensions>
</system.serviceModel>
Отредактировано для добавления
По запросу трассировка стека исключений выглядит следующим образом:
(System.ServiceModel.FaultException) This message cannot support the operation because it has been copied.
Server stack trace:
at System.ServiceModel.Channels.ServiceChannel.HandleReply(ProxyOperationRuntime operation, ProxyRpc& rpc)
at System.ServiceModel.Channels.ServiceChannel.Call(String action, Boolean oneway, ProxyOperationRuntime operation, Object[] ins, Object[] outs, TimeSpan timeout)
at System.ServiceModel.Channels.ServiceChannel.Call(String action, Boolean oneway, ProxyOperationRuntime operation, Object[] ins, Object[] outs)
at System.ServiceModel.Channels.ServiceChannelProxy.InvokeService(IMethodCallMessage methodCall, ProxyOperationRuntime operation)
at System.ServiceModel.Channels.ServiceChannelProxy.Invoke(IMessage message)
Exception rethrown at [0]:
at System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage reqMsg, IMessage retMsg)
at System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData& msgData, Int32 type)
at ConsoleApplication1.UserManagementService.IUserManagement.CreateUser(String username, String password, String[] systemCodes)
at ConsoleApplication1.UserManagementService.UserManagementClient.CreateUser(String username, String password, String[] systemCodes) in C:\Users\Paulo Santos\Documents\Visual Studio 2008\Projects\PJonDevelopment\ConsoleApplication1\ConsoleApplication1\Service References\UserManagementService\Reference.cs
at ConsoleApplication1.Program.Main(String[] args) in C:\Users\Paulo Santos\Documents\Visual Studio 2008\Projects\PJonDevelopment\ConsoleApplication1\ConsoleApplication1\Program.cs
Отредактировано для добавления
Как сказано в одном из комментариев, я разместил прототип проекта, который работает здесь: ServiceModel.zip
Я не могу не подчеркнуть, что прототип работает.Единственное, чего я не знаю, это то, почему я вдруг начал получать это странное сообщение.Я не копирую сообщение, а имею дело только с заголовками, и везде, где я ищу, говорят, что чтение сообщения - это большое «нет-нет».
Я боюсь того факта, что с таким количеством пунктов можно проверить, даже заменить,все сообщение в модели WCF , архитекторы спроектировали с таким объектом, что даже если вы посмотрите на него, он будет ужасен.
Если вы даете возможность осмотреть, сделайте твердое телообъект, который может выдержать тяготы бихинации, которыми управляет любой, кто хочет его осмотреть.