WCF Service host using ServiceHostFactory with Multiple Binding - wcf

I have created WCF service to host on IIS.
I am using ServiceHostFactory method to host my service(using Unity as DI).
I want to host my service using multiple binding, over the HTTP as well as over the TCP.
I tried giving base address, but its not taking. still giving me error as Service registered with HTTP schema.
Below code snippet might give you and idea.
public class MyServiceHostFactory : ServiceHostFactory
{
protected override ServiceHost CreateServiceHost(
Type serviceType, Uri[] baseAddresses)
{
MyServiceHost serviceHost = new MyServiceHost(serviceType, baseAddresses);
//configure container
MyFactory.Register();
return serviceHost;
}
}
Config file:
<system.serviceModel>
<services>
<service name="My.Service.MyService">
<host>
<baseAddresses>
<add baseAddress="http://localhost:9000/MyService/"/>
<add baseAddress="net.tcp://localhost:9001/MyService/"/>
</baseAddresses>
</host>
<endpoint address="Question" binding="basicHttpBinding" contract="My.Contract.IQuestionContract" />
<endpoint address="Answer" binding="basicHttpBinding" contract="My.Contract.IAnswerContract" />
<endpoint address="Question" binding="netTcpBinding" contract="My.Contract.IQuestionContract" />
<endpoint address="Answer" binding="netTcpBinding" contract="My.Contract.IAnswerContract" />
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="MyServicebehavior">
<serviceMetadata httpGetEnabled="True" httpsGetEnabled="True" />
</behavior>
</serviceBehaviors>
</behaviors>
<serviceHostingEnvironment multipleSiteBindingsEnabled="True">
</serviceHostingEnvironment>
Can anyone suggest me what can be done?
Main thing,
Is it possible to host service using ServiceHostFactory with Multiple Binding?
If Yes, can anyone help me how?

I'd try to remove base net.tcp address and specify full address on endpoint.

Related

WCF Discovery returns machine names in metadata (cannot be resolved)

So I have a WCF service hosted in IIS8 (Windows Server 2012). Here's the relevant part of the configuration file:
<system.serviceModel>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true"
multipleSiteBindingsEnabled="true" />
<services>
<service name="MovieCorner.DAL.Service.MovieCornerDalService">
<host>
<baseAddresses>
<add baseAddress="http://192.168.221.101/MovieCorner/" />
</baseAddresses>
</host>
<!-- Service Endpoints -->
<endpoint address="" binding="basicHttpBinding"
contract="MovieCorner.Commons.Services.IMovieCornerDalService">
<identity>
<dns value="localhost" />
</identity>
</endpoint>
<!-- Metadata Endpoints -->
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
<endpoint kind="udpDiscoveryEndpoint" />
</service>
</services>
<bindings>
<basicHttpBinding>
<binding maxBufferSize="2147483647" maxReceivedMessageSize="2147483647" />
</basicHttpBinding>
</bindings>
<behaviors>
<serviceBehaviors>
<behavior>
<serviceMetadata httpGetEnabled="True" httpsGetEnabled="True" />
<serviceDebug includeExceptionDetailInFaults="True" />
<serviceDiscovery />
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
A simple service with a simple binding, and with a discovery endpoint. The service is up and running, everything works fine. Almost...
Here's the code I'm using on the client side (it's just a "unit" test):
var client = new DiscoveryClient(new UdpDiscoveryEndpoint());
var response = client.Find(new FindCriteria(typeof(IMovieCornerDalService)));
Assert.IsNotNull(response);
Assert.IsNotNull(response.Endpoints);
Assert.IsTrue(response.Endpoints.Count > 0);
foreach (var endpoint in response.Endpoints)
{
Console.WriteLine("Address: {0}; Contract: {1}", endpoint.Address, endpoint.ContractTypeNames[0]);
}
The code successfully finds the only running service. The output is the following:
Address: http://ws12-iis8/MovieCorner/MovieCornerDalService.svc;
Contract: http://tempuri.org/:IMovieCornerDalService
The address is returned with the machine name that hosts the service. After the discovery I want to use the service like this:
var endpoint = response.Endpoints[0];
var clientProxy = ChannelFactory<IMovieCornerDalService>.CreateChannel(new BasicHttpBinding(), endpoint.Address);
var user = clientProxy.RegisterUser("1234"); // problem
The actual method call throws an exception, and the inner exception is the following: System.Net.WebException: The remote name could not be resolved: 'ws12-iis8'
The "unit" test runs in my PC, the service is hosted in a VM. I can reach the service at the http://192.168.221.101/MovieCorner/MovieCornerDalService.svc address. But not with the machine name address.
What am I missing? What are my options? How can I retrieve the actual (private) IP of the service hosting VM? I searched for different metadata options, but I'm not a pro in the web world, so I don't know what I'm looking for.
If you need more information, let me know. Thanks for your time!

WCF Error : Relative end point addresses

Um quite new to WCF . I think I have messed up a bit. So this is what I did so far and I ve hosted my WCF service in IIS
First the Contracts
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Web;
using System.Text;
using YangkeeServer.dto;
namespace YangkeeServer
{
public class Service1 : IService1
{
[WebInvoke(Method = "GET", ResponseFormat = WebMessageFormat.Json, UriTemplate = "single")]
public YangkeeTrailerDTO getTrailor()
{
return new YangkeeTrailerDTO()
{
loanFrom = "heaven"
};
}
[WebInvoke(Method = "GET",
ResponseFormat = WebMessageFormat.Json,
UriTemplate = "datum/{id}")]
public Test getName(string id)
{
return new Test()
{
Id = Convert.ToInt32(id) * 12,
Name = "Leo Messi"
};
}
}
}
and this is my web.config file
<?xml version="1.0"?>
<configuration>
<system.web>
<compilation debug="true" targetFramework="4.0" />
</system.web>
<system.serviceModel>
<services>
<service name="YangkeeServer.Service1">
<endpoint
contract="YangkeeServer.IService1"
binding="webHttpBinding"
behaviorConfiguration="WebHttp"
address="http://localhost:7000/Service1.svc">
</endpoint>
</service>
<service name="YangkeeServer.Service2">
<endpoint
contract="YangkeeServer.IService2"
binding="webHttpBinding"
behaviorConfiguration="WebHttp"
address="http://localhost:7000/Service2.svc">
</endpoint>
</service>
<service name="YangkeeServer.YangkeeTrailer">
<endpoint
contract="YangkeeServer.IYangkeeTrailor"
binding="webHttpBinding"
behaviorConfiguration="WebHttp"
address="http://localhost:7000/YangkeeTrailor.svc">
</endpoint>
</service>
</services>
<behaviors>
<endpointBehaviors>
<behavior name="WebHttp">
<webHttp />
</behavior>
</endpointBehaviors>
<serviceBehaviors>
<behavior name="">
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="false" />
</behavior>
</serviceBehaviors>
</behaviors>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
</system.serviceModel>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true"/>
</system.webServer>
</configuration>
and um using this urlhttp://localhost:7000/Service1.svc and um getting this error
Server Error in '/' Application.
When 'system.serviceModel/serviceHostingEnvironment/multipleSiteBindingsEnabled' is set to true in configuration, the endpoints are required to specify a relative address. If you are specifying a relative listen URI on the endpoint, then the address can be absolute. To fix this problem, specify a relative uri for endpoint 'http://localhost:7000/Service1.svc'.
can any one tell me where did I do wrong? Thank you in advance.
Set the service endpoint address to just the service filename (this is the relative part):
address="Service1.svc"
or set the address to blank for each endpoint (I don't think its needed when hosting in the development environment or in IIS)
address=""
See this answer to another question
The relevant part is:
the virtual directory (in IIS) where your *.svc file exists defines your service endpoint's address.
To fix this error, I added... listenUri="/" ... to the service endpoint.
Example:
<service name="_name_">
<endpoint address="http://localhost:_port_/.../_servicename_.svc"
name="_servicename_Endpoint"
binding="basicHttpBinding"
bindingConfiguration="GenericServiceBinding"
contract="_contractpath_._contractname_"
listenUri="/" />
</service>
MSDN: Multiple Endpoints at a Single ListenUri
This works for me:
1. Insert this lines inside service:
<host>
<baseAddresses>
<add baseAddress="http://localhost:7000/Service1.svc" />
</baseAddresses>
</host>
2. Set the value of address as bellow:
address=""
The full code:
<service name="YangkeeServer.Service1">
<host>
<baseAddresses>
<add baseAddress="http://localhost:7000/Service1.svc" />
</baseAddresses>
</host>
<endpoint
contract="YangkeeServer.IService1"
binding="webHttpBinding"
behaviorConfiguration="WebHttp"
address="">
</endpoint>
</service>

Cannot access WCF service from IE

This has probably been discussed however all the threads I saw on this topic did not help me hence I'm posting.
I am attempting to host a WCF HTTP service on IIS 5.1. It is extremely basic. I created a virtual directory in IE called wcftest, which points to the actual folder containing the contents of the service. Here is the structure:
Web.config
ConsoleWCF.svc
[App_Code] \ Program.cs
Here is the code for ConsoleWCF.svc
<%# ServiceHost Debug="true" Service="ConsoleWCF.WCFImplementer" Language="C#" %>
The Web.config looks like this:
<configuration>
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior name="ServiceBehavior">
<serviceMetadata httpGetEnabled="true"/>
</behavior>
</serviceBehaviors>
</behaviors>
<services>
<service name="ConsoleWCF.WCFImplementer"
behaviorConfiguration="ServiceBehavior">
<endpoint
address=""
binding="basicHttpBinding"
contract="ConsoleWCF.WCFInterface" />
<endpoint
address="mex"
binding="mexHttpBinding"
contract="IMetadataExchange" />
</service>
</services>
</system.serviceModel>
</configuration>
And finally the Program.cs is:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;
using System.ServiceModel.Web;
using System.ServiceModel.Description;
namespace ConsoleWCF
{
[ServiceContract]
public interface WCFInterface
{
[OperationContract]
[WebGet]
string GetData();
}
public class WCFImplementer : WCFInterface
{
public string GetData()
{
return "Tested Console WCF";
}
}
}
I can access this in IE by browsing to http://localhost/wcftest/ConsoleWCF.svc.
However I do not understand how to access the GetData method I have. When I did this using a stand-alone host, I had no issues accessing it. Any help is greatly appreciated.
In order for WCF to understand the [WebGet] attribute, the endpoint needs to have a certain configuration, namely use the webHttpBinding (not basicHttpBinding as you do) and to have a WebHttpBehavior added to it. If you change the web.config to something like the one below, you should be able to browse to http://localhost/wcftest/ConsoleWCF.svc/GetData.
<system.serviceModel>
<behaviors>
<endpointBehaviors>
<behavior name="REST">
<webHttp/>
</behavior>
</endpointBehaviors>
</behaviors>
<services>
<service name="ConsoleWCF.WCFImplementer">
<endpoint address=""
behaviorConfiguration="REST"
binding="webHttpBinding"
contract="ConsoleWCF.WCFInterface" />
</service>
</services>
</system.serviceModel>

My IIS does not recognize my WCF custom binding

Today, I have a problem with hosting my custom service host using custom binding. I have tried to implement ServiceHostFactory but when i right click to view with in browser, the error appeared as IIS does not recognize my custom binding (duplexHttpBinding).
My web.config is here:
<services>
<service name="TestWcf.Service1"
behaviorConfiguration="Service1Behavior">
<host>
<baseAddresses>
<add baseAddress="http://localhost:8888/Service1"/>
</baseAddresses>
</host>
<endpoint
address="http://localhost:9999/Service1"
binding="duplexHttpBinding"
bindingConfiguration="binding1"
contract="TestWcf.IService" />
</service>
</services>
<bindings>
<duplexHttpBinding>
<binding name="binding1"
closeTimeout="00:01:00"
openTimeout="00:01:00"
receiveTimeout="24.20:31:23.6470000"
sendTimeout="02:01:00"
session="ReliableSession"
sessionTimeout="00:10:00"
maxUndeliveredMessages="100"
maxMessagesInBatch="10"
maxPollingReplyInterval="00:02:00">
</binding>
</duplexHttpBinding>
</bindings>
<behaviors>
<serviceBehaviors>
<behavior name="Service1Behavior">
<serviceMetadata httpGetEnabled="True" />
<serviceDebug includeExceptionDetailInFaults="True" />
</behavior>
</serviceBehaviors>
</behaviors>
and code in dervied class is here:
public class CustomServiceHost : ServiceHostFactory
{
public override ServiceHostBase CreateServiceHost(string service, Uri[] baseAddresses)
{
DuplexHttpBinding binding = new DuplexHttpBinding();
binding.Name = "binding1";
Uri baseAddress = new Uri("http://localhost:8888/Service1");
Uri address = new Uri("http://localhost:9999/Service1");
ServiceHost serviceHost = new ServiceHost(typeof(Service1), baseAddresses);
serviceHost.AddServiceEndpoint(typeof(IService1), binding, address);
return serviceHost;
}
}
and in SVC file
<%# ServiceHost Language="C#" Debug="true" Service="TestWcf.Service1" Factory="TestWcf.CustomServiceHost" %>
Do I miss something in the context?
Thank you.
You must register new binding as binding extension in your configuration file.

Fail to send image ( byte[] ) as parameter of WCF service

I wrote some service that have method that get image ( byte[] ) as parameter ( return void ).
I also wrote some client (client & server run on same machien - different sulotion - using IIS )that send the bitmap ( as byte[] ) to the service - and each time i try to send i get the exception:
An error occurred while receiving the HTTP response to http://localhost/WebService/Service.svc. This could be due to the service endpoint binding not using the HTTP protocol. This could also be due to an HTTP request context being aborted by the server (possibly due to the service shutting down)
I added one more method that get void and return int - and i can call this method with no problem.
What can be wrong ? Do i need to define something speciel in the client service reference ?
The service method
[ServiceContract]
**public interface IService**
{
[OperationContract]
void GetPic( byte[] pic );
}
**public class Service : IService**
{
public void GetPic( byte[] pic )
{
...
}
}
Web.config file:
<system.serviceModel>
<services>
<service behaviorConfiguration="ServiceBehavior" name="ServiceProxy.Service">
<endpoint
name="basicHttp"
address=""
binding="basicHttpBinding"
bindingConfiguration=""
contract="Contracts.IService">
</endpoint>
<endpoint
address="mex"
binding="mexHttpBinding"
contract="IMetadataExchange" >
</endpoint>
<host>
<baseAddresses>
<add baseAddress="http://localhost:8731/ServiceProxy/" />
</baseAddresses>
</host>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="ServiceBehavior">
<serviceMetadata httpGetEnabled="True"/>
<serviceDebug includeExceptionDetailInFaults="False" />
</behavior>
</serviceBehaviors>
</behaviors>
You must configure your binding on server to accept large messages. By default it accepts only messages up to 65KB and arrays with 16k elements = in your case bitmap which has size less then 16KB.
Use this in your web.config (server side):
<bindings>
<basicHttpBinding>
<binding name="myBinding" maxReceivedMessageSize="1000000">
<readerQuotas maxArrayLength="1000000" />
</binding>
</basicHttpBinding>
</bindings>
In your endpoint configuration reference this binding in bindingConfiguration attribute by setting it to myBinding.