invoke WCF service method from web browser - c#

I want to run my service from the web browser: http://localhost:443/TestService//RunTest/data/test
It doesn`t work for me
This page can’t be displayed
•Make sure the web address http://localhost:443 is correct.
•Look for the page with your search engine.
•Refresh the page in a few minutes.
How to solve that - redefine endpoint - how?
The WCF service:
//TestService.svc.cs
public class TestService : ITestService
{
public string RunTest(string data)
{
return string.Format("You entered: {0}", data);
}
}
//ITestService.cs
[OperationContract]
[WebGet(ResponseFormat = WebMessageFormat.Json, UriTemplate = "/RunTest/data/{data}")]
string RunTest(string data)
{
return string.Format("You entered: {0}", proxyDomain);
}
//Web.config
<system.serviceModel>
<services>
<!-- This section is optional with the default configuration introduced
in .NET Framework 4.5.1 -->
<service
name="TestService">
<host>
<baseAddresses>
<add baseAddress="http://localhost:443/TestService/"/>
</baseAddresses>
</host>
<endpoint address="http://localhost:443/TestService"
binding="wsHttpBinding"
contract="ITestService" />
</service>
</services>
</system.serviceModel>
Also when I run it a WCF client is opened with port 54388

In my experience, you wouldn't be able to test directly via the browser.
Instead you should use a WCF Test Client:
http://msdn.microsoft.com/en-us/library/bb552364(v=vs.110).aspx
What you can do using your browser, is to see if you can reach the WSDL.
An example of a WSDL call in a browser:
http://localhost:8080/DecisionService/ws/PreTradeChecksRuleApp/1.0/PreTradeChecks/1.0?WSDL

You should add/change the endpoint "binding" attribute to "webHttpBinding" like this:
<endpoint address="http://localhost:443/TestService"
binding="webHttpBinding"
contract="ITestService" behaviorConfiguration="web" />
Or
<endpoint address="http://localhost:443/TestService"
binding="wsHttpBinding"
contract="ITestService" />
<endpoint address="http://localhost:443/TestService/web"
binding="webHttpBinding"
contract="ITestService" behaviorConfiguration="web"/>
In Both Cases you Have to Add:
<behaviors>
...
<endpointBehaviors>
<behavior name="web">
<webHttp/>
</behavior>
</endpointBehaviors>
...
</behaviors>
notes:
1) You have to add the attribute behaviorConfiguration to the webBinding and Add the behavior configuration
2) In the second solution, You have to change the name of the baseAddress because you can't have two endpoints configured to the same baseAddress (if anyone knows how to do it, please it would help me too)
Best Regards

Related

How to publish wcf service metadata when the wcf is self-hosted?

I googled for 2 days and tried almost everything, but I still can't get this stuff working.
I have 2 WCF services. I use self-hosting, not IIS(for some reasons IIS isn't working for me). One is duplex, another is standart. Here are their contracts:
Duplex:
[ServiceContract(SessionMode = SessionMode.Required, CallbackContract = typeof(IServiceCallback))]
public interface IClientService
{
[OperationContract(IsOneWay = true)]
void SolveTask(string pipelineName, string data);
[OperationContract(IsOneWay = true)]
void GenerateTask(List<GeneratorMethod> parameters);
[OperationContract]
bool Ping();
}
public interface IServiceCallback
{
[OperationContract(IsOneWay = true)]
void SendResult(SampleAnswer[] answers);
[OperationContract(IsOneWay = true)]
void RequestGeneratorParameters();
[OperationContract(IsOneWay = true)]
void SendGenerationResult(string text);
}
Classic:
[ServiceContract]
public interface IServerManagementService
{
[OperationContract]
[FaultContract(typeof(XmlError))]
[FaultContract(typeof(UnknownError))]
[FaultContract(typeof(InitializationError))]
void InitializeServer();
[OperationContract]
void StartServer();
[OperationContract]
void StopServer();
[OperationContract]
void RestartServer();
}
I have following config:
<configuration>
<services>
<service behaviorConfiguration="Service" name="LinProgWebServer.ClientService">
<endpoint address="net.tcp://localhost:8078/LinProgWebServer/ClientService"
binding="netTcpBinding" bindingConfiguration="netTcpEventBinding"
contract="LinProgWebServer.IClientService">
<identity>
<dns value="localhost" />
</identity>
</endpoint>
<endpoint address="mex" binding="mexHttpBinding" bindingConfiguration=""
contract="IMetadataExchange" />
<host>
<baseAddresses>
<add baseAddress="http://localhost:8731/Design_Time_Addresses/LinProgWebServer/ClientService" />
</baseAddresses>
</host>
</service>
<!--сервис управления сервером-->
<!--<service behaviorConfiguration="Service" name="LinProgWebServer.ServerManagementService">
<endpoint address="net.tcp://localhost:8079/LinProgWebServer/ManagementService"
binding="netTcpBinding" bindingConfiguration="netTcpEventBinding"
contract="LinProgWebServer.IServerManagementService">
<identity>
<dns value="localhost" />
</identity>
</endpoint>
<endpoint address="mex" binding="mexHttpBinding" bindingConfiguration=""
contract="IMetadataExchange" />
<host>
<baseAddresses>
<add baseAddress="http://localhost:8732/Design_Time_Addresses/LinProgWebServer/ManagementService" />
</baseAddresses>
</host>
</service>-->
</services>
<behaviors>
<serviceBehaviors>
<behavior name="Service">
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="false" />
</behavior>
<behavior name="">
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="false" />
</behavior>
</serviceBehaviors>
</behaviors>
Now i have a big trouble: I CAN find classic service via add service reference and CANNOT find duplex service. I tried netstat and it says that both services are listening on their ports. What am i doing wrong?
Here is exception i get:
There was an error downloading 'http://localhost:8731/Design_Time_Addresses/LinProgWebServer/ClientService/_vti_bin/ListData.svc/$metadata'.
The request failed with HTTP status 405: Method Not Allowed.
Metadata contains a reference that cannot be resolved: 'http://localhost:8731/Design_Time_Addresses/LinProgWebServer/ClientService'.
There was no endpoint listening at http://localhost:8731/Design_Time_Addresses/LinProgWebServer/ClientService that could accept the message. This is often caused by an incorrect address or SOAP action. See InnerException, if present, for more details.
The remote server returned an error: (404) Not Found.
If the service is defined in the current solution, try building the solution and adding the service reference again.
I'll be grateful for any help.
Make sure you .svc file has the correct name of the class you added in your Service Reference
if you added a service called 'Foo' it should look like:
<%# ServiceHost Language="C#" Debug="true" Service="Foo" CodeBehind="Foo.svc.cs" %
Also, make sure you have
In your web.config
I'm not sure whether this is going to be usefull. All my configs and services were fine, but i had a mistace in types, which were involved in work of wcf services, i haven't marked one of the types as datacontract. U'm very surprised why service started without erros and showed me such not informative messages. Also, thanks Yuval for reminding about InstanceContextMode attribute.
Add this to the area where you setup you set up your endpoint and reference your service classes:
//config service metadata
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.ServiceModel.Description;
ServiceMetadataBehavior mb = new ServiceMetadataBehavior();
ServiceHost.Description.Behaviors.Add(mb);
if (bUseSSL) {
mb.HttpsGetEnabled = true;
mb.HttpGetEnabled = false;
ServiceHost.AddServiceEndpoint(ServiceMetadataBehavior.MexContractName, MetadataExchangeBindings.CreateMexHttpsBinding(), "mex");
} else {
mb.HttpsGetEnabled = false;
mb.HttpGetEnabled = true;
ServiceHost.AddServiceEndpoint(ServiceMetadataBehavior.MexContractName, MetadataExchangeBindings.CreateMexHttpBinding(), "mex");
}
You should not be using the same URL that you were using to host it in the dev environment. Localhost means nothing outside of the machine, anyway. Use the IP address of the machine and also -- you might have to use netsh to open the port on that machine.

How adding an Interface to a WCF ServiceContract changes the URL of the methods

I am trying to fully understand how adding an Interface in WCF affects the URI of the methods. I have a ServiceContract defined like this:
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
[ServiceContract]
public class DataService
{
[OperationContract]
[WebGet(ResponseFormat = WebMessageFormat.Json)]
public List<List<string>> ListTestMethod()
{
return new List<List<string>>
{
new List<string> {"0", "Test String 1"},
new List<string> {"1", "Test String 2"},
new List<string> {"2", "Test String 3"}
};
}
}
In my web.config file I have the following:
<system.serviceModel>
<behaviors>
<endpointBehaviors>
<behavior name="epBehavior" >
<webHttp />
</behavior>
</endpointBehaviors>
<serviceBehaviors>
<behavior name="serviceBehavior">
<serviceDebug includeExceptionDetailInFaults="true"/>
</behavior>
</serviceBehaviors>
</behaviors>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true"
multipleSiteBindingsEnabled="true" />
<services>
<service name="DataService"
behaviorConfiguration="serviceBehavior">
<endpoint address=""
behaviorConfiguration="epBehavior"
binding="webHttpBinding"
contract="DataService" />
</service>
</services>
</system.serviceModel>
When I test the method via a browser:
http://localhost/DataService.svc/ListTestMethod
I get this which is the expected result:
[["0","Test String 1"],["1","Test String 2"],["2","Test String 3"]]
So now I would like to add an interface to the code behind with something like this:
[ServiceContract]
public interface IDataService
{
[OperationContract]
[WebGet(ResponseFormat = WebMessageFormat.Json)]
List<List<string>> ListTestMethod();
}
And of course go back to the DataService class and add the appropriate ": IDataService" implementation while removing the adorners that are now already in the Interface. Here is where I have trouble as the URL above no longer works.
I tried updating web.confg to this (note changes to name and contract attributes):
<services>
<service name="IDataService.DataService"
behaviorConfiguration="serviceBehavior">
<endpoint address=""
behaviorConfiguration="epBehavior"
binding="webHttpBinding"
contract="IDataService.DataService" />
</service>
</services>
Which seems to get the service going again but I cant actually get to the methods and if I add enable serviceMetadata it can no longer get to the metadata (it can in the original version). I have tried all kinds of combinations of the web.config and the URL but cannot seem to get my arms around it. How do I wire in the new Interface appropriately?
UPDATE
Thanks to venerik I got it working but changing the endpoint to point at the interface but leaving the service as is:
<services>
<service name="DataService"
behaviorConfiguration="serviceBehavior">
<endpoint address=""
behaviorConfiguration="epBehavior"
binding="webHttpBinding"
contract="IDataService.DataService" />
</service>
</services>
I'm not fully confident of this answer but I think your web.config should point to the interface:
<endpoint
...
contract="IDataService"/>
Your service host file should point to the concrete implementation:
<% #ServiceHost Language=C# Service="SomeNamespace.DataService" %>
Info about #ServiceHost

WCF RESTFul Service - 404 with endpoint not found with 2 services

I have two WCF services Exchange1.svc and Exchange2.svc both setup to be RESTful JSON consummables. Exchange1.svc works fine, but when I try to post to Exchange2.svc, I get an Endpoint not found message.
What am I doing wrong?
My IExchange2 interface is:
[ServiceContract]
public interface IExchange2
{
[System.ServiceModel.OperationContract(Name = "InsertReading")]
[WebInvoke(UriTemplate = "/InsertReading?memberID={memberID}", Method = "POST", ResponseFormat = WebMessageFormat.Json)]
void InsertReading(string memberID);
}
The URL I'm trying to hit is: http://localhost:49701/Exchange2.svc/DiaInsertReading?memberID=6519548
My config is:
<system.serviceModel>
<behaviors>
<endpointBehaviors>
<behavior name="MyNamespace.Exchange1Behavior">
<webHttp/>
</behavior>
<behavior name="MyNamespace.Exchange2Behavior">
<webHttp/>
</behavior>
</endpointBehaviors>
</behaviors>
<services>
<service name="MyNamespace.Exchange1">
<endpoint address="" binding="webHttpBinding" behaviorConfiguration="MyNamespace.Exchange1Behavior" contract="MyNamespace.IExchange1" />
</service>
<service name="MyNamespace.Exchange2">
<endpoint address="" binding="webHttpBinding" behaviorConfiguration="MyNamespace.Exchange2Behavior" contract="MyNamespace.IExchange2" />
</service></services></system.serviceModel>
I have edited my post since the answer did not help. Since you are hosting in IIS with svc you don't need to set an address in your binding as I was saying in my previous answer. The baseaddress will be the location of you server. Ex: http://localhost:49701/Exchange2.svc. If you hit this address you should get to a WCF Service webpage.
Since you are using POST method you can send the data in the request body. If you have fiddler installed, in the composer you can set the method to post and address to http://localhost:49701/Exchange2.svc/InsertReading if this is your address to your service.
In the body of the request body you set { memberID:"123" } change 123 to whatever value you want to send to your service.
Or you can send the data in the address like: http://localhost:49701/Exchange2.svc/InsertReading?memberID=123
If you now execute your request it should return a response 200 OK.
In web.config file specify your endpoint
<service name="MyNamespace.Exchange2">
<endpoint address="Exchange2" binding="webHttpBinding" behaviorConfiguration="MyNamespace.Exchange2Behavior" contract="MyNamespace.IExchange2" />
Then, add this end point in your URL as:
http://localhost:49071/Exchange2/DiaInsertReading?memberID=6519548

Two WCF services, hosted in one console application

I have one console app as a hosting for WCF service. Now, I'm going to add another one WCf service for administer purposes. So, here is my code:
[ServiceContract]
public interface IServiceAdmin
{
[OperationContract]
int GetCount();
}
[ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Multiple, InstanceContextMode = InstanceContextMode.Single)]
public class ServiceAdmin : IServiceAdmin
{
public int GetCount()
{
// It's just a stub to go on
return 1;
}
}
Here is excerpt of App.config applied to services:
<serviceBehaviors>
<behavior name="MyService.ServBehavior">
<dataContractSerializer maxItemsInObjectGraph="2147483646"/>
<serviceMetadata httpGetEnabled="false" />
<serviceDebug includeExceptionDetailInFaults="true" />
</behavior>
</serviceBehaviors>
</behaviors>
<services>
<service behaviorConfiguration="MyService.ServBehavior" name="MyService.MyServ">
<endpoint address="MyServ" behaviorConfiguration="" binding="netTcpBinding" contract="MyService.IMyServ" isSystemEndpoint="false" />
<endpoint address="mex" binding="mexTcpBinding" contract="IMetadataExchange" />
</service>
<service behaviorConfiguration="MyService.ServBehavior" name="MyService.MyServAdmin">
<endpoint address="MyServ" behaviorConfiguration="" binding="netTcpBinding" contract="MyService.IServiceAdmin" isSystemEndpoint="false" />
<endpoint address="mex" binding="mexTcpBinding" contract="IMetadataExchange" />
</service>
And here is how I get services started:
static void Main(string[] args)
{
ServiceHost myserviceHost = new ServiceHost(typeof(MyServ), new Uri("net.tcp://192.168.1.40:8730/"));
myserviceHost.Open();
ServiceHost myAdminHost = new ServiceHost(typeof(AServiceAdmin), new Uri("net.tcp://192.168.1.40:31337/");
myAdminHost.Open();
Console.ReadLine();
}
The issue is that regular service working good (metadata exchanging can provide info on service methods) and another service (which I mentioned at the beginning, administer service) is not working at all.
That is the reason of it?
Thanks in advance!
The issue was in wrong name of service in App.Config. The right line is
<service behaviorConfiguration="MyService.ServBehavior" name="MyService.ServiceAdmin">

Strange error when trying to start my WCF service with webHttpBinding

I'm getting this strange error when I try connect to my WCF with webHttpBinding service from a web browser:
Sendera:ActionNotSupportedThe message with Action '' cannot be processed at the receiver, due to a ContractFilter mismatch at the EndpointDispatcher. This may be because of either a contract mismatch (mismatched Actions between sender and receiver) or a binding/security mismatch between the sender and the receiver. Check that sender and receiver have the same contract and the same binding (including security requirements, e.g. Message, Transport, None).
My app.config:
<services>
<service name="MyNamespace.MyService">
<host>
<baseAddresses>
<add baseAddress="http://localhost:9091/MyService/" />
</baseAddresses>
</host>
<endpoint address="" binding="webHttpBinding" contract="MyNamespace.IMyService" />
</service>
</services>
My method simply looks like this:
[WebGet(UriTemplate = "foo/{id}")]
public string GetFoo(string id)
{ ...
OK - I would expect you're probably missing the endpoint behavior needed - try this config:
<behaviors>
<endpointBehaviors>
<behavior name="web">
<webHttp/>
</behavior>
</endpointBehaviors>
</behaviors>
<services>
<service name="MyNamespace.MyService">
<host>
<baseAddresses>
<add baseAddress="http://localhost:9091/MyService/" />
</baseAddresses>
</host>
<endpoint
address=""
behaviorConfiguration="web"
binding="webHttpBinding"
contract="MyNamespace.IMyService" />
</service>
</services>
When you updated your method from GetFoo(string fooID) to GetFoo(string id), did you also update your contract in IMyService with the updated parameter name of id?
Reference of your previous question: Is there a way to have custom defined friendly URLs with WCF without IIS?

Categories