WCF Service Datacontract got replaced with OperationContract name - wcf

After adding my wcf to website data contract got replaced with operation contract. How to get back like code 2
code1
[OperationContract(Action = "http://tempuri.org/IDocument/GetFile", ReplyAction = "http://tempuri.org/IDocument/GetFileResponse")] 
        [XmlSerializerFormat(SupportFaults = true)] 
        GetFileResponse GetFile(GetFileRequest request);
code2
[OperationContract(Action = "http://tempuri.org/IDocument/GetFile", ReplyAction = "http://tempuri.org/IDocument/GetFileResponse")]
AppFile GetFile(AppFile objFile);

Related

How to get the WCF service address from DynamicEndpoint

I Crreated a DynamicEndpoint to find the WCF service automatically.
namespace Client
{
class Program
{
static void Main(string[] args)
{
DynamicEndpoint dynamicEndpoint = new DynamicEndpoint(ContractDescription.GetContract(typeof(ICalculator)), new NetTcpBinding());
using (ChannelFactory<ICalculator> channelFactory = new ChannelFactory<ICalculator>(dynamicEndpoint))
{
ICalculator caculate = channelFactory.CreateChannel();
Console.WriteLine("x + y = {2} when x = {0} and y = {1}", 4, 9, caculate.Add(4, 9));
Console.WriteLine("Find service, the service address is: " + dynamicEndpoint.Address.Uri);
}
Console.Read();
}
}
}
The problem is when I try to print the service address, the return value is
http://schemas.microsoft.com/discovery/dynamic
That's not the real service address I published.
1. How to get the real service address?
2. If there are multiple services available, which one will DynamicEndpoint choose? Can I get the address array or list?
As far as I know, we could not get the actual use endpoint in client. except that we use the OperationContext object,which provides access to the execution context of a service method.
https://learn.microsoft.com/en-us/dotnet/api/system.servicemodel.operationcontext?redirectedfrom=MSDN&view=netframework-4.7.2
For example, we could refer to the following code to get the actual endpoint.
Server.
public string GetAddress()
{
OperationContext oc = OperationContext.Current;
string result=oc.Channel.LocalAddress.Uri.ToString();
return result;
}
Client.
ChannelFactory<IService> factory = new ChannelFactory<IService>(dynamicEndpoint);
IService sv = factory.CreateChannel();
Console.WriteLine(sv.GetAddress());
Besides,I don't think dynamic endpoint could list the endpoints that have been found. Dynamic Endpoint merge service discovery with service invokation. when a service is invoked using a dynamic endpoint, it will depend on the FindCriteria property to find the service endpoint and then invokes it.
https://learn.microsoft.com/en-us/dotnet/api/system.servicemodel.discovery.dynamicendpoint?view=netframework-4.7.2
https://learn.microsoft.com/en-us/dotnet/api/system.servicemodel.discovery.findcriteria?view=netframework-4.7.2

WCF SOAP and REST together

Lets say I have WCF Soap Services and I am using this library for SOAP headers
http://wcfextras.codeplex.com/
For example my interface looks like this
[SoapHeader("HelperHeader", typeof(HelperHeader), Direction = SoapHeaderDirection.In)]
[OperationContract]
string GetData(string id);
////////
public string GetData(string id)
{
HelperHeader clientHeader=SoapHeaderHelper<HelperHeader>.GetInputHeader("HelperHeader");
if (clientHeader != null)
return id
}
In Header class i have user name and password for basicHttpbinding.
Now i want to use this method "GetData" for REST service . (I also have second webHttbinding) . I want to use this Method "GetData" for REST clients , now i find that i can use attributes WebGet and Webinvoke
[OperationContract]
[WebGet(UriTemplate = "testjson/{id}", ResponseFormat = WebMessageFormat.Json)]
string GetData(string id);
My quietion is how i can use One Method "GetData" for both REST and SOAP services and with user name and password .?
When you create a HttpRequest you can add whatever you want to headers collection:
WebRequest request = WebRequest.Create("<URI>");
request.Headers.Add("username", "<UserName>");
request.Headers.Add("password", "<Pass>");
request.GetResponse();
and in the Service implementation, you can easily access to headers collection by calling this property WebOperationContext.Current.IncomingRequest.Headers

How to ge thet data from WCF Ria Service method that returns IQueryable<> using ChannelFactory

I have a WCF RIA Service with methods that return IQueryable<>. I want to access this methods using ClannelFactory from a
console application. I have an interface on the client that matches the the methods in my RIA Service. When I run the server and
the client applications I can see that the server method is called and an IQuery<> object is returned. The problem is that on the
client I can't get the data sent by the server. I can see that data actually comes by using Fiddler, but I think that the data can't be
deserialized to IQueryable.
For me the type of the data received doesn't matter. I'll be happy with just an array. But because the method in the
service returns IQueryable my OperationContract method on the client has the same type.
So the question is how to get the data from the server, without changing the return type (IQueryable) on the server side?
Server side:
public IQueryable<Customers> GetCustomers()
{
List<Customers> customersList = new List<Customers>();
customersList.Add(new Customer())
...
return customersList.AsQueryable();
}
Client side:
[ServiceContract]
public interface CustoemrsService
{
[OperationContract]
IQueryable<Customers> GetCustomers();
}
And the ChannelFactory code:
var endpointAddress = new EndpointAddress(_endpointAddress);
var channelFactory = new ChannelFactory<VfxSystemDomainServiceSoap>(new BasicHttpBinding());
var channel = channelFactory.CreateChannel(endpointAddress);
IQueryable<Customers> customersCollection = channel.GetVfxfopenQuery();

WCF service consume, no response at all

Sorry to bother you guys again.
I am going to consume a WCF service on a server. The service was created by outside. If I look at it in the browser, it is fine. Please see the image below.
To consume it, I add service reference. with the url http://wsvc01/BOERPI/BOERPI.svc
Then I instantiate the proxy by the code.
BOERPI.PostPhoneCallResponse client = null;
client = new BOERPI.PostPhoneCallResponse();
double x = client.ActualCallCharge; // suppose to get a proper value but not
Some of the code of the service is:
[ServiceContract]
public interface iBOERPI
{
[OperationContract]
PostPhoneCallResponse PostPhoneCall(PostPhoneCallRequest objCDRRequest);
[DataContract]
public class PostPhoneCallResponse
{
[DataMember]
public double ActualCallCharge = -1.0;
I assume the service code is 100% right, is any thing wrong when I consume the service?
When I righted click the definition of PostPhoneCallResponse, it is:
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.Runtime.Serialization", "4.0.0.0")]
[System.Runtime.Serialization.DataContractAttribute(Name="PostPhoneCallResponse", Namespace="http://schemas.datacontract.org/2004/07/nsBOERPI")]
[System.SerializableAttribute()]
public partial class PostPhoneCallResponse : object, System.Runtime.Serialization.IExtensibleDataObject, System.ComponentModel.INotifyPropertyChanged {
[System.NonSerializedAttribute()]
private System.Runtime.Serialization.ExtensionDataObject extensionDataField;
[System.Runtime.Serialization.OptionalFieldAttribute()]
private double ActualCallChargeField;
Thanks.
client = new BOERPI.PostPhoneCallResponse(); You are trying to use your DataContract here instead of Service client.
Check under Service References for your service name you used in your client application and
use it:
eg.
using(var client = new BingMapsGeocodeService()) // This should be your service client name
{
}
Update:
Sending and Received messages using request and response objects:
You need to create a request object as per your operation shows:
var request = new PostPhoneCallRequest(){ // populate all your properties you need to send to the service};
var client = new BOERPI.MyClient(); // Instantiate your client with the name you have given for your service client.
PostPhoneCallResponse response = client.PostPhoneCall(request); // You are sending your request and getting a response as PostPhoneCallResponse object

Accessing asmx WebService Using WCF

I am trying to access an old ASMX webservice using WCF by calling the ChannelFactory.CreateChannel() method.
If the web service is created by WCF, everything is straightforward. I can instantiate the proxy client generated by the svcutil tool, or manually call the ChannelFactory.CreateChannel() method. Afterwards, I can call the web service methods the same way for both scenarios.
But if the web service is of the old ASMX variety, I can still instantiate the proxy either way, but I am unable to call the same web service method.
For example, assume this basic WCF web service interface:
[ServiceContract]
public interface IWebService
{
[OperationContract]
string HelloWorld();
}
After using svcutil to generate the proxy, I can call HelloWorld() one of 2 ways:
WebServiceClient proxy = new ServiceReference.WebServiceClient();
textBox1.Text += proxy.HelloWorld();
or:
ChannelFactory<ServiceReference.IWebService2> cfactory =
new ChannelFactory<ServiceReference.IWebService>("BasicHttpBinding_IWebService");
ServiceReference.IWebService proxy = cfactory.CreateChannel();
((IClientChannel)proxy).Open();
textBox1.Text += proxy.HelloWorld();
Now assume this ASMX web service:
[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
public class WebService : System.Web.Services.WebService
{
public WebService() { }
[WebMethod]
public string HelloWorld()
{
return "Hello World";
}
}
Calling HelloWorld() using the SoapClient generated by svcutil tool is nearly the same as if it were a WCF web service:
WebServiceSoapClient proxy = new ServiceReference.WebServiceSoapClient();
textBox1.Text += proxy.HelloWorld();
But trying to call HelloWorld() if you create the channel yourself and you will get an error:
ChannelFactory<ServiceReference.WebServiceSoap> cfactory =
new ChannelFactory<ServiceReference.WebServiceSoap>("WebServiceSoap");
ServiceReference.WebServiceSoap proxy = cfactory.CreateChannel();
((IClientChannel)proxy).Open();
textBox1.Text += proxy.HelloWorld();
The error is "No overload for method HelloWorld takes 0 arguments".
It appears it is because the HelloWorld method in the autogenerated interface (ServiceReference.WebServiceSoap) takes an argument of type ServiceReference.HelloWorldRequest.
So in the end, I was only able to make it work by looking through the svcutil generated code and change my implementation to this:
ChannelFactory<ServiceReference.WebServiceSoap> cfactory =
new ChannelFactory<ServiceReference.WebServiceSoap>("WebServiceSoap");
ServiceReference.WebServiceSoap proxy = cfactory.CreateChannel();
((IClientChannel)proxy).Open();
ServiceReference.HelloWorldRequest inValue =
new WCFConsumeWebServices.ServiceReference.HelloWorldRequest();
inValue.Body = new WCFConsumeWebServices.ServiceReference.HelloWorldRequestBody();
ServiceReference.HelloWorldResponse retVal = proxy.HelloWorld(inValue);
textBox1.Text += retVal.Body.HelloWorldResult;
Is this how it is suppose to be?
For one type of basic http web service, we get to use virtually the same code to call a method, but for another we need to muck through the generated proxy code and have different implementation depending on how you open the channel ?