WCF Client in VS2005 - wcf

I'm trying to implement a WCF client in a VS2005 project. In VS2010 it is all working fine, because I just can add the service reference. For the VS2005 I've builded the .config and the Service1.cs with the svcutil. The two files are added in the project and I also added the service reference as a web reference.
Further you find the two files of that were generated.
<system.serviceModel>
<bindings>
<wsHttpBinding>
<binding name="SDTRfServerClass.WCFService.WSHttpBinding_IService1" />
</wsHttpBinding>
</bindings>
<client>
<endpoint address="http://192.168.0.102:8732/Design_Time_Addresses/Calc/Service1/"
binding="wsHttpBinding" bindingConfiguration="WSHttpBinding_IService1"
contract="SDTRfServerClass.WCFService.IService1" name="WSHttpBinding_IService1">
<identity>
<dns value="localhost" />
</identity>
</endpoint>
</client>
</system.serviceModel>
This is the app.config which I also tried to change to web.config, but that doesn't make any difference.
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "4.0.0.0")]
[System.ServiceModel.ServiceContractAttribute(ConfigurationName = "IService1")]
public interface IService1
{
[System.ServiceModel.OperationContractAttribute(Action = "http://tempuri.org/IService1/Add", ReplyAction = "http://tempuri.org/IService1/AddResponse")]
double Add(double n1, double n2);
[System.ServiceModel.OperationContractAttribute(Action = "http://tempuri.org/IService1/Substract", ReplyAction = "http://tempuri.org/IService1/SubstractResponse")]
double Substract(double n1, double n2);
[System.ServiceModel.OperationContractAttribute(Action = "http://tempuri.org/IService1/Multiply", ReplyAction = "http://tempuri.org/IService1/MultiplyResponse")]
double Multiply(double n1, double n2);
[System.ServiceModel.OperationContractAttribute(Action = "http://tempuri.org/IService1/Divide", ReplyAction = "http://tempuri.org/IService1/DivideResponse")]
double Divide(double n1, double n2);
}
This is a part of the Service1.cs.
When I try to call the service with the following code I get the error "Could not find the endpointelement with the name WSHttpBinding_IService1 and contract IService1 in the configuration part of the ServiceMode-client. This can be caused if the configuration of the applicaton is not found or that there was found an endpoint which equalize the name.
I've tried to change the name with the full solution name at all places.
Does anyone as a solution?
client = new Service1Client("WSHttpBinding_IService1");
double result = client.Add(Double.Parse("2"), Double.Parse("4"));
I also tried to use the plug-in for VS2005 to add service reference which create a .map and a .cs file, but I'm keep getting the same error.

I think you have some typo problem or you have wrong namespace because error means that .NET cannot find information about your endpoint.
Try post your complete web.config and I've look at it
Or you can use dynamic channel factory like this and don't worry about linking to your web.config
WSHttpBinding myBinding = new WSHttpBinding();
//define endpoint url (where service is deployed)
EndpointAddress myEndpoint = new EndpointAddress("http://192.168.0.102:8732/Design_Time_Addresses/Calc/Service1/"); //change to real endpoint
//Use channel factory instead of generated one
ChannelFactory<IService1> myChannelFactory = new ChannelFactory<IService1>(myBinding, myEndpoint); //Change to you WCF interface
IService1 myServiceClient = myChannelFactory.CreateChannel();
//and call it
var result = myServiceClient.Add(1,1); //input to your method
//other methods
((IClientChannel)myServiceClient).Close();
myChannelFactory.Close();

Related

wcf - how to handle a service with multiple endpoints that share the same action

i get the following error when trying to start my service:
Could not start the Service: System.InvalidOperationException: This service has multiple endpoints listening at 'https://b2e.my.loc:8093/' which share the same initiating action 'http://localhost:8080/kestrel/AirService'. As a result, messages with this action would be dropped since the dispatcher would not be able to determine the correct endpoint for handling the message. Please consider hosting these Endpoints at separate ListenUris.
We got an application that is using a third party WSDL in order to search and book flight.
and we have another winform application that takes the generated reference.cs from the above wsdl
the idea is to create a "simulator" so instead of invoking the real WSDL we are actually invoking the simulator itself and generating the data we need (sort of mocking)
consider the following reference.cs file generated by the WSDL:
namespace FlightWCF
{
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "4.0.0.0")]
[System.ServiceModel.ServiceContractAttribute(Namespace = "", ConfigurationName = "FlightWCF.ISearch")]
public interface ISearch
{
[System.ServiceModel.OperationContractAttribute(Action = "http://localhost:8080/kestrel/AirService", ReplyAction = "*")]
FlightWCF.serviceResponse1 service(FlightWCF.serviceRequest1 request);
}
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.ServiceModel", "4.0.0.0")]
[System.ServiceModel.ServiceContractAttribute(Namespace = "", ConfigurationName = "FlightWCF.IReserve")]
public interface IReserve
{
[System.ServiceModel.OperationContractAttribute(Action = "http://localhost:8080/kestrel/AirService", ReplyAction = "*")]
FlightWCF.serviceResponse6 service(FlightWCF.serviceRequest6 request);
}
}
this is part of my app.config
<service name="MyFlightClass.ServiceFlight">
<endpoint address="" binding="basicHttpBinding" bindingConfiguration="basicSecureHttpBindingConfiguration" contract="FlightWCF.ISearch" />
<endpoint address="" binding="basicHttpBinding" bindingConfiguration="basicSecureHttpBindingConfiguration" contract="FlightWCF.IReserve" />
</service>
and this is the service that is using the above code:
namespace MyFlightClass
{
class ServiceFlight : ISearch, IReserve
{
public FlightWCF.serviceResponse1 service(FlightWCF.serviceRequest1 request)
{
//DO SOMETHING
}
public FlightWCF.serviceResponse6 service(FlightWCF.serviceRequest6 request)
{
//DO SOMETHING
}
}
}
the problem is that both service uses that same "Action".
if i change the "Action" of one if them, it becomes unreachable.
and i can't find any data on how to configure a service with 2 endpoints that have different contracts but with the same action.
the suggestion "Please consider hosting these Endpoints at separate ListenUris" is unclear to me.
The main problem is that the double service endpoint address shall not be same. The configuration you provided has the same listening Uri.
<service name="MyFlightClass.ServiceFlight">
<endpoint address="" binding="basicHttpBinding" bindingConfiguration="basicSecureHttpBindingConfiguration" contract="FlightWCF.ISearch" />
<endpoint address="" binding="basicHttpBinding" bindingConfiguration="basicSecureHttpBindingConfiguration" contract="FlightWCF.IReserve" />
</service>
So it results in that the operation has the same namespace since the operation name is duplicated. But the SOAP message is sent to the right endpoint depending on the soap operation namespace.
In a short, we shall have to change the service endpoint address in the configuration.
Feel free to let me know if there is anything I can help with.

WCF REST service doesn't seems to work - configuration issue?

I have a WCF service with custom binding, hosted in IIS (IIS Express in development) with following service contract:
[ServiceContract]
public interface IServer
{
[OperationContract]
StreamCollection GetStreams(Guid poolKey);
[OperationContract]
PoolCollection GetPools();
[OperationContract]
StreamEntity GetStream(Guid poolKey, string localIndex);
}
It works OK (from client and also I can see it's metadata discovered ok in WCFTestClient).
I have to expose its functionality as REST, so I created a new contract as below
[ServiceContract]
public interface IRestServer
{
[OperationContract(Name="GetStreamsREST")]
[WebGet(UriTemplate = "pool/{poolKey}/streams")]
StreamCollection GetStreams(string poolKey);
[OperationContract(Name = "GetPoolsREST")]
[WebGet(UriTemplate = "pools")]
PoolCollection GetPools();
[OperationContract(Name = "GetStreamREST")]
[WebGet(UriTemplate = "pool/{poolKey}/stream/{localIndex}")]
StreamEntity GetStream(string poolKey, string localIndex);
}
I have both interfaces implemented in the same service class.
The web.config file is
<behaviors>
<endpointBehaviors>
<behavior name="webHttp">
<webHttp/>
</behavior>
</endpointBehaviors>
</behaviors>
<bindings>
<customBinding>
<binding name="CustomBinding">
<binaryMessageEncoding />
<httpTransport maxReceivedMessageSize="655360" />
</binding>
</customBinding>
</bindings>
<services>
<service behaviorConfiguration="ServiceBehavior" name="MyServ.Server.Server">
<endpoint address="" binding="customBinding" bindingConfiguration="CustomBinding" contract="MyServ.Server.IServer" />
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
<endpoint address="rest" behaviorConfiguration="webHttp" binding="webHttpBinding" contract="MyServ.Server.IRestServer" />
</service>
</services>
However, when I browse to access the service using rest, witha url like
http://localhost:<myport>/Service.svc/pools
http://localhost:<myport>/Service.svc/pool/somekey/streams
http://localhost:<myport>/Service.svc/pool/somekey/streams
I get error 404.
I put a break-point in some methods and attached debugger to IIS process, but it seems nothing gets called.
If I check the service metadata with WCFTestClient, it just sees IService, but not IRestService. Is this normal? EDIT: Yes, it seems it is (check this)
Thanks for any suggestion.
REST endpoints do not expose metadata in a way which can be consumed by the WCFTestClient, which explains why you can't access it. And the address you're browsing is incorrect, since you specified the endpoint address for the REST endpoint as "rest", you need to access them in something like
http://localhost:port/Service.svc/rest/pool/myPoolKey/streams
http://localhost:port/Service.svc/rest/pools
http://localhost:port/Service.svc/rest/myPoolKey/stream/1
Another thing: the Name attribute in the [OperationContract] attribute doesn't matter for REST endpoints, so you can drop it (it doesn't hurt having it there, though). Also, if you're using .NET 4.0, you don't even need the [OperationContract] attribute at all, given that you already have [WebGet], so your interface can be defined as
[ServiceContract]
public interface IRestServer
{
[WebGet(UriTemplate = "pool/{poolKey}/streams")]
StreamCollection GetStreams(string poolKey);
[WebGet(UriTemplate = "pools")]
PoolCollection GetPools();
[WebGet(UriTemplate = "pool/{poolKey}/stream/{localIndex}")]
StreamEntity GetStream(string poolKey, string localIndex);
}
Are you able to post your code on how you are calling the WCF service? I had a similar problem the other day where the client app was calling the page with a HTTP POST instead of a HTTP GET, and thus getting a 404 error.
[WebInvoke(Method = "POST", BodyStyle = WebMessageBodyStyle.Wrapped, ResponseFormat = WebMessageFormat.Json, UriTemplate = "/GuessWhat")]
vs
[WebGet(UriTemplate = "/GuessWhat/{variable}", ResponseFormat = WebMessageFormat.Json)]
Im not sure if your service has this or not but make sure the service that is implementing your Service Contract has this attribute.
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
Thanks all for all suggestions.
However, I solved the issue finally.
The problem is I don't know still what was the problem, but I decided to take a different and more "clean" way.
So what I did was to create a different service SVC file, RestServer, where I implemented the REST methods
And I modified the settings in web config to have two different services, one for original one (pure WCF) and one for REST one, as below
<service name="MyServ.Server.RestServer" >
<endpoint address="" name="RESTEndpoint" behaviorConfiguration="webHttp" binding="webHttpBinding" contract="MyServ.Server.IRestServer" />
</service>
And this did the trick.
Actually, I should use this approach from the very beginning, to comply with single responsability principle ...

How to use ServiceRoutes while defining maxReceivedMessageSize for non-custom bindings in WCF

Editing this to refocus on the actual issue. I've preserved the origional question at the bottom of the message but changing the title and content to reflect what was really happening.
I need to override the maxReceivedMessageSize for a WCF service added to an MVC3 project via the ServiceRoute mechanism. Specifing the binding in the web.config doesn't work. How does one do this.
Initial question is below this line but is misleading based on lots of false positives I was seeing.
Hi I have used some examples to add a file streaming upload service to my MVC3 project. If I use the default bindings (i.e., not defined in web.config) the service works as long as I don't exceed the 64k default size. When I try and define my own binding to increase the size I get a content-type mismatch in my trace and a HTTP415 Unsupported Media Type in the response. I'm trying to call this via fiddler via HTTP and am not using a WCF client.
Here is the error in the trace:
Content Type image/jpeg was sent to a service expecting multipart/related;type="application/xop+xml". The client and service bindings may be mismatched.
Here is the web.config service model section
<system.serviceModel>
<behaviors>
<endpointBehaviors>
<behavior name="NewBehavior0" />
</endpointBehaviors>
</behaviors>
<services>
<service name="AvyProViewer.FileService">
<endpoint address="UploadFile" binding="basicHttpBinding" bindingConfiguration=""
contract="AvyProViewer.FileService" />
</service>
</services>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true"/>
<bindings>
<basicHttpBinding>
<binding name="NewBinding0" maxBufferSize="2147483647" maxReceivedMessageSize="2147483647"
messageEncoding="Mtom" transferMode="StreamedRequest">
<readerQuotas maxDepth="2147483647" maxStringContentLength="2147483647"
maxArrayLength="2147483647" maxBytesPerRead="2147483647" maxNameTableCharCount="2147483647" />
</binding>
</basicHttpBinding>
</bindings>
Here is the service:
[ServiceContract]
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
public class FileService
{
[OperationContract]
[WebInvoke(Method = "POST", UriTemplate = "UploadFile")]
public string UploadFile(Stream fileStream)
{
string path = HostingEnvironment.MapPath("~");
string fileName = Guid.NewGuid().ToString() + ".jpg";
FileStream fileToupload = new FileStream(path + "\\FileUpload\\" + fileName, FileMode.Create);
byte[] bytearray = new byte[10000];
int bytesRead, totalBytesRead = 0;
do
{
bytesRead = fileStream.Read(bytearray, 0, bytearray.Length);
totalBytesRead += bytesRead;
} while (bytesRead > 0);
fileToupload.Write(bytearray, 0, bytearray.Length);
fileToupload.Close();
fileToupload.Dispose();
return fileName;
}
}
And here is where I expose it in my MVC3 routes:
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.Add(new ServiceRoute("FileService", new WebServiceHostFactory(), typeof(FileService)));
. . .
}
I think the issue is with the mtom declaration for messageEncoding in your binding. Try changing messageEncoding to Text.
Answer ended up being a combination of three different stack overflow posts. None by themselves solved the question but each provided crucial clues as to what was happing.
It seems that if you add a ServiceRoute the web.config binding information is ignored. This SO post clued me in to what seems to be undocumented behavior of this function: Unable to set maxReceivedMessageSize through web.config
I then used this post to determine how to programatically override the maxreceivedmesssagesize for the binding: Specifying a WCF binding when using ServiceRoute.
Unfortunately the code form #2 didn't work out of the box (not sure if the binding behavior for ServiceRoute has changed or what makes the difference). Turns out that if you specify a ServiceRoute its automatically created as a CustomBinding which can't be cast to the WebHTTPBinding type used in #2. So this post: How to set the MaxReceivedMessageSize programatically when using a WCF Client? helped me determine how to change the code in #2 to add this capability to a custom binding.

Edit System.Servicemodel values programmatically?

When using WCF, there is a section in the web.config as below.
<system.serviceModel>
<services>
<service name="abc">
<endpoint /> <---this
</service>
</services>
</system.serviceModel>
Is it possible to edit the area I've marked programmatically?
I can see there is a sytem.serviceModel namespace, but other than that I'm a bit lost.
If you want to change these parameters at runtime you can override ServiceHost.OnOpening()
E.g. to change port:
protected override void OnOpening()
{
foreach (ServiceEndpoint endpoint in Description.Endpoints)
{
string uriString = string.Format("{0}://{1}:{2}{3}",
endpoint.Address.Uri.Scheme,
endpoint.Address.Uri.Host,
endpoint.Address.Uri.Port + _basePort,
endpoint.Address.Uri.LocalPath);
endpoint.Address = new EndpointAddress(uriString);
}
base.OnOpening();
}
To complement Mike Mozhaev's answer, since your service is hosted in IIS you'll need a ServiceHostFactory to get a reference to the service host (or to use your own host). There's some information about it at http://blogs.msdn.com/b/carlosfigueira/archive/2011/06/14/wcf-extensibility-servicehostfactory.aspx.

WCF - Contract Name could not be found in the list of contracts

I am relatively new to WCF. However, I need to create a service that exposes data to both Silverlight and AJAX client applications. In an attempt to accomplish this, I have created the following service to serve as a proof of concept:
[ServiceContract(Namespace="urn:MyCompany.MyProject.Services")]
public interface IJsonService
{
[OperationContract]
[WebInvoke(Method = "GET",
RequestFormat=WebMessageFormat.Json,
ResponseFormat = WebMessageFormat.Json)]
List<String> JsonFindNames();
}
[ServiceContract(Namespace="urn:MyCompany.MyProject.Services")]
public interface IWsService
{
[OperationContract(Name="FindNames")]
List<String> WsFindNames();
}
[ServiceBehavior(Name="myService", Namespace="urn:MyCompany.MyProject.Services")]
public class myService : IJsonService, IWsService
{
public List<String> JsonFindNames()
{ return FindNames(); }
public List<String> WsFindNames()
{ return FindNames(name); }
public List<string> FindNames()
{
List<string> names = List<string>();
names.Add("Alan");
names.Add("Bill");
return results;
}
}
When I try to access this service, I receive the following error:
The contract name 'myService' could not be found in the list of contracts implemented by the service 'myService'.
What is the cause of this? How do I fix this?
Thank you
Your contract is the Interface not the implementation.
Somewhere in the config you have written myService instead of IJsonService.
Remove the namespace from Service name. It will work fine.
Modify your web.config
You can find <services> tag and below of this tag you have to have two other tag :
<service ....
And
<endpoint ....
In <endpoint> tag you have to reference to interface of your class.
For exampl : If your service class named CustomerSearch and your interface named ICustomerSearch you have to config like this :
<service name="CustomerSearch" behaviorConfiguration="ServiceBehavior">
<endpoint address="" binding="webHttpBinding" contract="ICustomerSearch"
behaviorConfiguration="ServiceAspNetAjaxBehavior">
I had the same issue, but my solution was that in my web.config, I was specifying the entire class name (including namespace), whereas WCF would only accept a class name.
This didn't work:
<services>
<service name="BusinessServices.Web.RfsProcessor">
This worked:
<services>
<service name="RfsProcessor">
I have had that error before for ServiceModel framework 3.5, and I checked my host's config file. I found it was my cut-and-paste error. My service was pointing to an old non-existing service than the one I am using. It starts working again after I corrected these lines like below:
<system.serviceModel>
<services>
<!--<service name="NotUsed.Serv">-->
<service name="InUse.MyService">
<host>
<baseAddresses>
<!--<add baseAddress="http://localhost:8181/LastService" />-->
<add baseAddress="http://localhost:8181/InUseService"/>
</baseAddresses>
</host>
</service>
</services>
</system.serviceModel>
Note that MyService has to be the name of your contract class in ServiceModel 3.5 BUT IT IS IMyService contract interface in Framework 4.0 -->
namespace InUse {
[ServiceContract]
public interface IMyService
{
[WebGet(UriTemplate = "/GetList/{PATTERN}",
RequestFormat = WebMessageFormat.Json,
ResponseFormat = WebMessageFormat.Json)]
[OperationContract]
List<string> GetIDListByPattern(string PATTERN);
}
[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]
public class MyService : IMyService
{
List<string> MySample = (new _PointRT()).Sample().Select(r=>r._pointXID).ToList();
public List<string> GetIDListByPattern(string PATTERN) {
return MySample.Where(x => x.Contains(PATTERN)).ToList();
}
}
In the web.config file, the <service element's name attribute needs to be the service type's name with the namespace, but not the assembly (Namespace1.Namespace2.Class). The <endpoint element's contract attribute similarly has namespace-qualified interface type - Namespace1.Namespace2.Interface.
This also solves all behavior shenanigans, like CreateBehavior not being invokes on BehaviorExtensionElement.