Action and ReplyAction in WCF Proxy - wcf

What is the use of Action and ReplyAction in OperationContract attribute ?

Action defines your input uri for the soap operation for your service method.
Reply Action defines the output uri for your service method.
They are basically used to customize the uri for both. See below.
[ServiceContract]
public partial interface IServiceContract
{
[OperationContract(
Action = "http://mynamspace/v1/IServiceContract/Input/ServiceMethod",
ReplyAction = "http://mynamspace/v1/IServiceContract/Output/ServiceMethod")]
SomeResponseType ServiceMethod(SomeRequestType x);
In your wsdl you would see
<wsdl:portType name="IServiceContract">
<wsdl:operation name="ServiceMethod">
<wsdl:input wsaw:Action="http://mynamspace/v1/IServiceContract/Input/ServiceMethod" name="SomeRequestType" message="tns:SomeRequestType " />
<wsdl:output wsaw:Action="http://mynamspace/v1/IServiceContract/Output/ServiceMethod" name="SomeResponseType" message="tns:SomeResponseType " />
That make sense?

Its for WS addressing.
Introduction to WS-Addressing: http://www.fpml.org/_wgmail/_bpwgmail/pdfdz3oYx1M9e.pdf
http://www.w3.org/Submission/ws-addressing/
Look at the reply soap message:
http://msdn.microsoft.com/en-us/library/system.servicemodel.operationcontractattribute.action.aspx

Related

WCF use of SOAP gives error when deserializing response defined in WSDL as empty message

I'm very new to WCF and the related technologies. (Using WCF 4.0, by the way.)
Here are some snippets from the WSDL file for a web service that I need to interface with.
<wsdl:binding name="MPGWCSTAOperations_v1_1SoapBinding" type="impl:MPGWCSTAOperations">
<wsdlsoap:binding transport="http://schemas.xmlsoap.org/soap/http" />
...
<wsdl:operation name="MonitorStartLine">
<wsdlsoap:operation soapAction="urn:v1_1.csta.ws.mpgw.gintel.com/MonitorStart" />
<wsdl:input name="MonitorStartLineRequest">
<wsdlsoap:body use="literal" />
</wsdl:input>
<wsdl:output name="MonitorStartLineResponse">
<wsdlsoap:body use="literal" />
</wsdl:output>
</wsdl:operation>
...
</wsdl:binding>
<wsdl:portType name="MPGWCSTAOperations">
...
<wsdl:operation name="MonitorStartLine" parameterOrder="monitorStartLine">
<wsdl:input name="MonitorStartLineRequest" message="impl:MonitorStartLineRequest" />
<wsdl:output name="MonitorStartLineResponse" message="impl:MonitorStartLineResponse" />
</wsdl:operation>
....
</wsdl:portType>
<wsdl:message name="MonitorStartLineResponse" />
My understanding is that the MonitorStartLine operation is defined to return a response message MonitorStartLineResponse, which is defined to be an empty message.
I've used Visual Studio's Project - Add Service Reference facility to generate C# proxy code for this.
Then I do something like this:
MPGWCSTAOperationsClient cstaOperationsClient = new MPGWCSTAOperationsClient();
MonitorStartLine monitorStartLine = new MonitorStartLine();
monitorStartLine.pnis = new string[] {"0000032"};
cstaOperationsClient.MonitorStartLine(monitorStartLine);
This results in the following exception:
System.ServiceModel.CommunicationException was unhandled
HResult=-2146233087
Message=Error in deserializing body of reply message for operation 'MonitorStartLine'.
End element 'Body' from namespace 'http://schemas.xmlsoap.org/soap/envelope/' expected.
Found element 'monitorStartLineResponse' from namespace 'urn:v1_1.csta.ws.mpgw.gintel.com'. Line 1, position 296.
Source=mscorlib
Using Fiddler I'm seeing the response as follows:
HTTP/1.1 200 OK
Server: Apache-Coyote/1.1
X-Powered-By: Servlet 2.5; JBoss-5.0/JBossWeb-2.1
Content-Type: text/xml;charset=utf-8
Transfer-Encoding: chunked
Date: Wed, 16 Oct 2013 22:01:44 GMT
149
<?xml version="1.0" encoding="utf-8"?>
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<soapenv:Body>
<monitorStartLineResponse xmlns="urn:v1_1.csta.ws.mpgw.gintel.com"/>
</soapenv:Body>
</soapenv:Envelope>
Which looks to me like it conforms to the WSDL.
I'm thinking that I can probably just ignore the error (the server will never be the wiser), but I'd prefer to fix the problem if possible.
The message conforms to the WSDL, but in a place where the WSDL specification is ambiguous. .NET is expecting nothing within the Body element, because no message parts were defined. The sender is sending an empty monitorStartLineResponse element instead, as though a single message part were specified, with an element named monitorStartLineResponse.
Because of areas where the WSDL specification is ambiguous, the Web Services Interoperability Organization was formed. The WS-I Basic Profile 1.1 specification was developed to specify a subset of WSDL which is guaranteed to be interoperable across platforms.
This WSDL does not conform to WS-I BP 1.1.
In fact, from reading the WSDL 1.1 spec (section 3.4, soap:operation), I see that this will be taken to be a "document-literal binding" because there are no "style" attributes saying otherwise.
In section 4.4.1, Bindings and Parts, R2213, the WS-I BP 1.1 spec says:
R2213 In a doc-literal description where the value of the parts attribute of soapbind:body is an empty string, the corresponding ENVELOPE MUST have no element content in the soap:Body element.
That is what .NET is expecting, but it's not what .NET is receiving.
Here's the workaround that I implemented. (It is debatable as to whether it's better to implement a workaround or to just ignore the exception - I prefer to do it this way.)
What I'm doing is modifying the response message before WCF invokes SOAP processing on it. I'm simply removing the XML element that WCF/SOAP don't think should be there.
/// <summary>
/// This class is used to provide a workaround for a problem due to the (censored) server sending
/// responses encoded in SOAP which do not, at least according to WCF standards, conform to the
/// WSDL specifications published for the server.
/// </summary>
public class MessageInspector : IClientMessageInspector
{
public object BeforeSendRequest(ref Message requestMessage, IClientChannel clientChannel)
{
return null; // Method not needed
}
public void AfterReceiveReply(ref Message replyMessage, object correlationState)
{
if (replyMessage.IsFault)
return; // Avoid distortion of SOAP fault messages
string messageBody;
using (MemoryStream memoryStream = new MemoryStream())
{
using (XmlWriter xmlWriter = XmlWriter.Create(memoryStream))
{
replyMessage.WriteMessage(xmlWriter);
xmlWriter.Flush();
messageBody = Encoding.UTF8.GetString(memoryStream.ToArray());
}
}
messageBody = messageBody.Replace(
"<monitorStartLineResponse xmlns=\"urn:v1_1.csta.ws.mpgw.gintel.com\" />", "");
using (MemoryStream memoryStream = new MemoryStream(Encoding.UTF8.GetBytes(messageBody)))
{
using (XmlDictionaryReader xmlDictionaryReader =
XmlDictionaryReader.CreateTextReader(memoryStream, new XmlDictionaryReaderQuotas()))
{
Message newMessage =
Message.CreateMessage(xmlDictionaryReader, int.MaxValue, replyMessage.Version);
newMessage.Properties.CopyProperties(replyMessage.Properties);
replyMessage = newMessage;
}
}
}
}
/// <summary>
/// Class needed to inject the above MessageInspector class into the WCF processing of messages.
/// </summary>
public class InjectInspectorBehavior : IEndpointBehavior
{
public void Validate(ServiceEndpoint serviceEndpoint)
{
// Method not needed
}
public void AddBindingParameters(ServiceEndpoint serviceEndpoint,
BindingParameterCollection bindingParameters)
{
// Method not needed
}
public void ApplyDispatchBehavior(ServiceEndpoint serviceEndpoint,
EndpointDispatcher endpointDispatcher)
{
// Method not needed
}
public void ApplyClientBehavior(ServiceEndpoint serviceEndpoint, ClientRuntime clientRuntime)
{
clientRuntime.MessageInspectors.Add(new MessageInspector());
}
}
This is put into operation by adding the second line shown here:
_cstaOperationsClient = new MPGWCSTAOperationsClient();
_cstaOperationsClient.Endpoint.Behaviors.Add(new InjectInspectorBehavior());
The above code is largely based on code found in these two locations:
http://blogs.msdn.com/b/kaevans/archive/2008/01/08/modify-message-content-with-wcf.aspx
Replacing content of WCF Message

Can someone tell me if Colfusion 8 can consume a WCF service?

I cant find any good samples for that scenario.
Also, the WCF service used the Entity Framework 6.0 which should return big JSON structures.
For now I am just trying to find a simple example which can call a simple WCF service:
[ServiceContract]
public interface ITest
{
[OperationContract(Name = "Test_GetDate")]
[WebGet(UriTemplate = "/GetDate", RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json)]
string GetDate();
...
public class Test : ITest
{
public string GetDate()
{
return (DateTime.UtcNow.ToString());
}
...
Thank you
Yes it can. This scenario worked for me, but I was using XML format (WCF SOAP) not rest/json, but You can try.
-I use soap UI to figure out how soap Envelope should look like. This tool is free http://www.soapui.org/ and it is easy to use.
-Create New Soap UI project and paste WSDL address in the input, application will generate empty XML request - soap envelope.
-You can test your service from this app
-I am using cfhttp to invoke service from cf:
We figured out soap envelope and we put this in cf variable :
<cfsavecontent variable="soapBody">
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:tem="http://tempuri.org/" xmlns:ozon="http://schemas.datacontract.org/blah/prc">
<soapenv:Header/>
<soapenv:Body>
<tem:myservicemethod>
<tem:someParameter1>This is my first param</tem:someParameter1>
<tem:someParameter2>
<blah:AC>This is my second parameter</blah:AC>
</tem:someParameter2>
</tem:myservicemethod>
</soapenv:Body>
</soapenv:Envelope>
</cfsavecontent>
Now invoke service. This I digged from Ben Nadel's blog : http://www.bennadel.com/blog/1809-Making-SOAP-Web-Service-Requests-With-ColdFusion-And-CFHTTP.htm
<cfhttp
url="http:/SomeService/Service.svc"
method="post"
result="httpResponse">
<!---
TIP : Look into your WSDL to figure out SOAPAction value
--->
<cfhttpparam
type="header"
name="SOAPAction"
value="http://tempuri.org/SomeService/myservicemethod"
/>
<cfhttpparam
type="header"
name="accept-encoding"
value="no-compression"
/>
<cfhttpparam
type="xml"
value="#trim( soapBody )#"
/>
</cfhttp>
<cfdump var="#httpResponse#" />

How can I generate a valid WCF proxy for a service that has a period in the message types?

I am interfacing with a web service I have no control over and it has messages (input/output) and actions that contain periods (.)
When svcutil generates the proxy, it includes:
[MessageContractAttribute(WrapperName="The.Request",...)]
public partial class TheRequest
{ ... }
[MessageContractAttribute(WrapperName="The.Response",...)]
public partial class TheResponse
{ ... }
which model the WSDL:
<wsdl:message name="The.Request">
<wsdl:part name="Input" type="tns:InputType" />
</wsdl:message>
<wsdl:message name="The.Response">
<wsdl:part name="Return" type="tns:Return" />
</wsdl:message>
When the code is run, I get an error message:
RPC Message TheRequest in operation DoIt has an invalid body name Input. It must be TheRequest
Stack Trace:
at System.ServiceModel.Description.XmlSerializerOperationBehavior.Reflector.OperationReflector.EnsureMessageInfos()
at System.ServiceModel.Description.XmlSerializerOperationBehavior.Reflector.EnsureMessageInfos()
at System.ServiceModel.Description.XmlSerializerOperationBehavior.Reflector.OperationReflector.get_Request()
at System.ServiceModel.Description.XmlSerializerOperationBehavior.CreateFormatter()
at System.ServiceModel.Description.XmlSerializerOperationBehavior.System.ServiceModel.Description.IOperationBehavior.ApplyClientBehavior(OperationDescription description, ClientOperation proxy)
at System.ServiceModel.Description.DispatcherBuilder.BindOperations(ContractDescription contract, ClientRuntime proxy, DispatchRuntime dispatch)
at System.ServiceModel.Description.DispatcherBuilder.ApplyClientBehavior(ServiceEndpoint serviceEndpoint, ClientRuntime clientRuntime)
at System.ServiceModel.Description.DispatcherBuilder.BuildProxyBehavior(ServiceEndpoint serviceEndpoint, BindingParameterCollection& parameters)
at System.ServiceModel.Channels.ServiceChannelFactory.BuildChannelFactory(ServiceEndpoint serviceEndpoint, Boolean useActiveAutoClose)
at System.ServiceModel.ChannelFactory.CreateFactory()
....
I can't find a way to change the validation to accept the message name.
Can anyone clue me in on what to do or, at least, point me in the right direction?
Thanks.

method not allowed error while using wcf webinvoke post

Hi following is Operation Contract , where im trring to insert some data , so im using WebInvoke POST method, but when im calling this method its giving me an error saying "Method not allowed"
do i have to change any configuration settings for allowing POST calls in web.config?
[OperationContract]
[WebInvoke(
UriTemplate = "/Album/PostData?name={name}&CrBy={createdBy}" ,
Method="POST")]
void PostUserData(string name, string createdBy);
and im calling my service as below
http://localhost:2170/MySampleService.svc/xml/Album/PostData?name=devpost&CrBy=postadmin
Well you should use Method="GET" if you want to call your service like this. Also the definition of the method name and arguments don't seem to match your query string.
If you want to use POST verb then you need to send a POST request and you will not be able to invoke the service by directly typing the url in the browser.
you need to add in web.config
1.
<endpoint address="customBinding" binding="customBinding" bindingConfiguration="basicConfig" contract="WcfRest.IService1"/>
2.
<bindings>
<customBinding>
<binding name="basicConfig">
<binaryMessageEncoding/>
<httpTransport transferMode="Streamed" maxReceivedMessageSize="67108864"/>
</binding>
</customBinding>
</bindings>
Change your method in the interface as
public class InputClass
{
public string Name{get;set;}
public string CreatedBy{get;set}
}
[OperationContract]
[WebInvoke(
UriTemplate = "PostUserData" ,
Method="POST",
BodyStyle = WebMessageBodyStyle.WrappedRequest,
ResponseFormat = WebMessageFormat.Json,
RequestFormat = WebMessageFormat.Json))]
void PostUserData(InputClass input);
See the link for more info.http://fszlin.dymetis.com/post/2010/05/10/Comsuming-WCF-Services-With-Android.aspx
Are you calling your service from javascript in a browser?
Does the html page reside in the same domain as the wcf service?
If they are not in the same domain, then I would say that it is a cross-site-scripting issue. I belive GET is allowed cross-sites, but POST are not. http://en.wikipedia.org/wiki/JSONP would be a solution, if it's supported server-side (by WCF)

Issue adding service reference for wcf

Warning 1 Custom tool warning: Cannot import wsdl:binding
Detail: The given key was not present in the dictionary.
XPath to Error Source: //wsdl:definitions[#targetNamespace='http://wrapper.dao.ccarwebservice.ids.com']/wsdl:binding[#name='CCaRWebServiceHttpBinding'] C:\Users\me\Documents\Visual Studio 2008 \Projects\CcarsWcfTest\CcarsWcfTest\Service References\ServiceReference1\Reference.svcmap 1 1 CcarsWcfTest
what can I do to resolve this issue?
I've tried running the service utility from the command prompt and adding a service reference to my project. I've also gone into the advanced setting in the Add Service Reference dialog and deselected 'Reuse types in all referenced assemblies'.
EDIT
Here is the part of the wsdl I think it's referring to..
<wsdl:binding name="CCaRWebServiceHttpBinding" type="ns:CCaRWebServicePortType">
<http:binding verb="POST"/>
<wsdl:operation name="fnGetccarprogramsummaryarray">
<http:operation location="CCaRWebService/fnGetccarprogramsummaryarray"/>
<wsdl:input>
<mime:content type="text/xml" part="fnGetccarprogramsummaryarray"/>
</wsdl:input>
<wsdl:output>
<mime:content type="text/xml" part="fnGetccarprogramsummaryarray"/>
</wsdl:output>
</wsdl:operation>
<wsdl:operation name="fnGetccarprogramsummary">
<http:operation location="CCaRWebService/fnGetccarprogramsummary"/>
<wsdl:input>
<mime:content type="text/xml" part="fnGetccarprogramsummary"/>
</wsdl:input>
<wsdl:output>
<mime:content type="text/xml" part="fnGetccarprogramsummary"/>
</wsdl:output>
</wsdl:operation>
</wsdl:binding>
public partial class fnGetccarprogramsummaryarrayRequest
{
public fnGetccarprogramsummaryarrayRequest()
{
}
}
the others are like this...
public partial class fnGetccarprogramsummaryRequest
{
[System.ServiceModel.MessageBodyMemberAttribute(Namespace="http://wrapper.com", Order=0)]
[System.Xml.Serialization.XmlElementAttribute(IsNullable=true)]
public string programAcronym;
public fnGetccarprogramsummaryRequest()
{
}
public fnGetccarprogramsummaryRequest(string programAcronym)
{
this.programAcronym = programAcronym;
}
}
Where did the WSDL come from? How was it generated?
It could be the the definition of the input and return types are missing.
fnGetccarprogramsummaryarray
fnGetccarprogramsummary.
It could be that it is trying to look for the definition in an array of types and not finding it.
EDIT
I think that I found it you have a POST binding and the tool only supports a SOAP binding
http://social.msdn.microsoft.com/Forums/en/wcf/thread/859a2c87-02db-469d-ab65-c558ff091e61
The key that is not present is then the SOAP binding.
After searching.. the only solution I've come across is to ignore this error.
"It is internal implementation detail of svcutil.
The error is probably since the wsdl contains a POST binding and the utlity only works on SOAP bindings. But if there is another SOAP binding in the wsdl it works."