Send information in Soap Header to WCF service in C# - wcf

i want a web application to create a service reference to my WCF service, insert information to the header of the soap call and call my WCF method.
i read about MessageContract attribute and declared one in the interface file:
[MessageContract]
public class BasicServiceHeader
{
[MessageHeader]
public string myString;
}
my WCf interface is:
[ServiceContract]
public interface IBasicService
{
[OperationContract]
[WebGet(UriTemplate = "GetData?value={value}")] // Add support for HTTP GET Requests
string GetData(int value);}
i don't want the BasicServiceHeader to be passed as a parameter of GetData function , i want to keep the function as it is and to extract the BasicServiceHeader inside the function, can i do that ?

Client side, you can pass a header prior invoking the operation:
MessageHeader messageHeader = MessageHeader.CreateHeader(_headerName, _headersNameSpace, _headerValue);
OperationContext.Current.OutgoingMessageHeaders.Add(messageHeader);
and extract it using FindHeader service side

Related

Calling a Web Service using WCF channel Factory.Is it possible?

In the project I am working on I need to call webservices (asmx).I would like to call them using wcf and using the channelfactory(No adding service Reference).
Some might have an interface(contract)many dont.
Is there an end to end example how to do it?
var service=ChannelFactory<?>... How do I get the webserviceContract.
Surely this must be a common scenario to be able to call a webservice (asmx)
Thanks for your time
To expand upon my comment, you should be able to create an interface that has methods that match the web service methods in the asmx service. For example:
Web Service Methods
string GetMessage()
void SendMessage(string message)
int AddNumbers(int x, int y)
Service Contract
[ServiceContract]
public interface IServiceName
{
[OperationContract]
string GetMessage();
[OperationContract]
void SendMessage(string message);
[OperationContract]
int AddNumbers(int x, int y)
}
ChannelFactory
ChannelFactory<IServiceName> serviceFactory =
new ChannelFactory<IServiceName>(new BasicHttpBinding(),
"http://www.services.com/Service.asmx");
Not 100% sure this will work, but it would be easy to try out. Also, you'd probably want to set the namespace on the service contract ([ServiceContract(Namespace = "somenamespace")]) to match the legacy asmx service, otherwise the messages might not get processed.

Why am I getting an InvalidOperationException after adding a [MessageContract] attribute?

The operation 'PRPA_IN201301UV02' could not be loaded because it has a parameter or return type of type System.ServiceModel.Channels.Message or a type that has MessageContractAttribute and other parameters of different types. When using System.ServiceModel.Channels.Message or types with MessageContractAttribute, the method must not use any other types of parameters.
I'm running a WCF on a console host, this is the contract:
[MessageContract]
public class opRequest
{
[MessageBodyMember]
public string myProperty;
}
[ServiceContract(Namespace = "urn:hl7-org:v3")]
public interface IHL7v3
{
[OperationContract(Name = "PRPA_IN201301UV02", Action = "urn:hl7-org:v3:PRPA_IN201301UV02")]
string PIXManager_PRPA_IN201301UV02(opRequest clientID);
}
It does run when I remove from opRequest class the [MessageContract] and [MessageBodyMember]
I'm completely not sure if that will get me to what I need, so i'll give the wider scope - I'm trying to get the SOAP body to be without an enclosing tag of the parameter name.
for example (the body extract from the SOAP message) instead of:
<s:Body>
<PRPA_IN201301UV02 xmlns="urn:hl7-org:v3">
<clientID>the xml document is enclosed</clientID>
</PRPA_IN201301UV02>
I want it to be like this:
<s:Body>
<PRPA_IN201301UV02 xmlns="urn:hl7-org:v3">
my given xml document will go here...
</PRPA_IN201301UV02>
I need it like that to conform to a standard (HL7v3 PIX Manager SOAP Web Service).
Any ideas?
Looks like you should use MessageContract for your return parameter as well
EDITED:
Have a look at this MSDN article for more details Using Message Contracts
If you design your contract with messages you can't use other types either as a parameter or a return value.
Here is a code snippet from the article:
[OperationContract]
bool Validate(BankingTransaction bt);
// Invalid, the return type is not a message contract.
[OperationContract]
void Reconcile(BankingTransaction bt1, BankingTransaction bt2);
// Invalid, there is more than one parameter.
Did you try to use an XMLDocument as the input parameter instead of opRequest? You will also have to mark the interface to use the XML Serializer:
[ServiceContract(Namespace = "urn:hl7-org:v3")]
[XmlSerializerFormat]
public interface IHL7v3
{
[OperationContract(Name = "PRPA_IN201301UV02", Action = "urn:hl7-org:v3:PRPA_IN201301UV02")]
XMLDocument PIXManager_PRPA_IN201301UV02(XMLDocument doc);
}
I am presuming you are also returning XML.
Please note that this is wide open - any XML can be sent which may not be what you intend as there no explicit data contract.

WCF MessageContract clarification please

I'm bit confused with how MessageContract Attribute works in WCF.
When I put the MessageContract the proxy shows two parameters instead of 1.
e.g.
GetResultResponse GetOperation(GetResultRequest request)
[MessageContract]
public class GetResultRequest
{
[MessageHeader]
public Header Header { get; set; }
[MessageBodyMember]
public List<Person> PersonList { get; set; }
}
The proxy generates this method signature:
GetOperation(ref Header, List<Person> personList)
When I remove MEssageContract Attributes:
Proxy Generates correct signatures:
GetOperation(GetResultRequest request)
Could anyone please confirm if this is the expected behavour?
That is default behavior. When you generate proxy it doesn't create message contracts by default. You can turn this on in advanced configuration in Add Service reference (by checking Always generate message contracts) or by /messageContract switch in svcutil. Once you turn it on you will get methods with single message contract parameter as you have on the service.
Unless you have the specific requirement to mark the header with the MessageHeader attribute, try to change the class attribute to Datacontract and your properties to DataMember attributes and see if the behaviour changes. As far as I know, unless you implement a custom serializer you cannot influence how svcutil will create your proxy.

WCF Additional Proxy Classes

I have a WCF webservice that has the following service contract
[ServiceContract(Namespace = "http://example.org")]
public interface IEquinoxWebservice
{
[OperationContract]
Guid Init();
[OperationContract]
List<Message> Dequeue(Guid instanceId);
[OperationContract]
void Enqueue(Guid instanceId, Message message);
[OperationContract]
void Dispose(string instanceId);
}
Message class is an abstract class that is implemented by a bunch of concrete message classes.
I want to make all the concrete message classes available in the client proxy that is generated. Not just the message class.
Is there any way to make them available as types in the webservice so the standard Visual Studio proxy generator will create them?
You need to specify those types. See Data Contract Known Types.

RESTful WCF service that can respond in both JSON(P) and XML and still be used as SOAP web service?

Given a contract such as:
[ServiceContract] public interface IService
{
[OperationContract]
[WebGet(UriTemplate = "GetData/{id}.{format}")]
ResponseData GetData(string id, string format);
}
Is there a way to get the service to respond with json when requested as:
/GetData/1234.json, xml when requested as /GetData/1234.xml and still be available as a proper soap service at some other url, with a strongly typed wsdl contract?
Using a Stream as the return value for GetData is not workable, as though it fufills the first two requirements, wcf can't create a full wsdl specification as it has no idea what the contents of the resultant Stream will be.
You should have two separate methods which take id and format (and they would call a shared implementation that returns ResponseData) which have different WebGet attributes:
[ServiceContract]
public interface IService
{
[OperationContract]
[WebGet(UriTemplate = "GetData/{id}.{format}.xml",
ResponseFormat=WebMessageFormat.Xml)]
ResponseData GetDataXml(string id, string format);
[OperationContract]
[WebGet(UriTemplate = "GetData/{id}.{format}.json",
ResponseFormat=WebMessageFormat.Json)]
ResponseData GetDataJson(string id, string format);
}
For the SOAP endpoint, you should be able to call either method, but you are going to have to have a separate ServiceHost instance hosting the implementation of the contract.