Как говорит Марк, у вас есть контракт на обслуживание, который принимает параметры сообщения. Но вам не нужно создавать XML вручную, вместо этого вы можете совместно использовать интерфейс и сообщения в общей DLL, которая является общей как для сервера, так и для клиента.
Например, у меня есть часть программного обеспечения, которая принимает сообщения, потому что спецификация говорит, что это было необходимо. У меня есть общая сборка, которая содержит интерфейс, все потенциальные сообщения с запросами и ответами и открытые статические строки для пространств имен. Итак, для одной из операций это выглядит следующим образом
[ServiceContract(
Namespace = Constants.Service.Namespace.Location,
Name = "ServiceMonitorContract")]
public interface IMonitor
{
[OperationContract(
Action = Constants.Service.Actions.GetTasksRequest,
ReplyAction = Constants.Service.Actions.GetTasksResponse)]
Message GetTasks(Message request);
}
и у меня есть контракты сообщений, которые выглядят как
[MessageContract(IsWrapped = true,
WrapperNamespace = Constants.Messages.Namespace.Location)]
public sealed class GetTasksRequest
{
....
}
Чтобы подключиться к услуге, я делаю следующее
private static IMonitor GetChannelToWebService()
{
EndpointAddress endpoint = new EndpointAddress("http://example/service.svc");
ChannelFactory<IMonitor> channelFactory =
new ChannelFactory<IMonitor>(new BasicHttpBinding(), endpoint);
return channelFactory.CreateChannel();
}
И тогда я могу сделать следующее, чтобы использовать его с общими сообщениями.
IMonitor channel = GetChannelToWebService();
// Create the GetTasksRequest message
GetTasksRequest getTasksRequest = new GetTasksRequest();
// Set the various properties on the message
// Convert it to a strongly type message
TypedMessageConverter requestMessageConverter = TypedMessageConverter.Create(
typeof(GetTasksRequest),
Constants.Service.Actions.GetTasksRequest,
Constants.Service.Namespace.Location);
Message request = requestMessageConverter.ToMessage(
getTasksRequest,
MessageVersion.Soap11);
// Send it and get the response.
Message response = channel.GetTasks(request);
// Check for SOAP faults
if (response.IsFault)
{
MessageFault fault = MessageFault.CreateFault(response, int.MaxValue);
// React accordingly
}
TypedMessageConverter responseMessageConverter = TypedMessageConverter.Create(
typeof(GetTasksResponse),
Constants.Service.Actions.GetTasksResponse,
Constants.Service.Namespace.Location);
GetTasksResponse getTasksResponse =
responseMessageConverter.FromMessage(response) as GetTasksResponse;
((IClientChannel)channel).Close();
Единственное, о чем нужно знать, это то, что ошибки не будут переданы клиентской стороне. Вы должны проверить объект Message, когда он возвращается в качестве ответа вручную, и действовать соответственно, как вы можете видеть из примера.
Серверная часть. Я делаю то же самое с TypedMessageConvertor
// Convert the inbound message to a GetTasksRequest.
TypedMessageConverter getTasksMessageConverter = TypedMessageConverter.Create(
typeof(GetTasksRequest),
Constants.Service.Actions.GetTasksRequest,
Constants.Service.Namespace.Location);
GetTasksRequest getTasksMessage =
getTasksMessageConverter.FromMessage(request) as GetTasksRequest;
// Validate the message is the correct type.
if (getTasksMessage == null)
{
throw FaultHelper.UnknownMessageTypeFault();
}
// Do my thing
GetTasksResponse responseMessage = new GetTasksResponse();
// Set appropriate response bits in the responseMessage
TypedMessageConverter responseConverter = TypedMessageConverter.Create(
typeof(GetTasksResponse),
Constants.Service.Actions.GetTasksResponse,
Constants.Service.Namespace.Location);
Message response = responseConverter.ToMessage(responseMessage, request.Version);
response.Headers.RelatesTo = request.Headers.MessageId;
return response;
Только не забудьте установить заголовок RelatesTo в качестве MessageId из заголовков запроса