WCF Project library - c#

I want to migrate my WCF serivce from WebSite App_Code folder to project library.
As far as I know, WCF library is able to read web config about service model, so the only action I did was following:
1 - Create new project library and put all code about wcf from app_code to it.
2 - Modify web config in order to point at service class with full qualified name (namespace + class name)
3 - Modify svc file in order to point at service class instance with full qualifide name.
However, my service is not running anymore. I'm using ws-httpbinding with custom validator, but it seems my service expect a basic http binding.
The error I'm struggling with appears like this:
the request of message must be protected, such as required by a contract operation ('IMyService','http://tempuri.org/'). The protection must be implemented by ('BasicHttpBinding','http://tempuri.org/') binding.
##EDIT:
My Web.Config:
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior name="MyBehavior">
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true" />
<serviceCredentials>
<userNameAuthentication userNamePasswordValidationMode="Custom" customUserNamePasswordValidatorType="MyWcfNamespaceOfMyDLL.MyCustomValidator" />
<serviceCertificate findValue="localhost" x509FindType="FindBySubjectName" storeLocation="LocalMachine" storeName="My" />
</serviceCredentials>
</behavior>
</serviceBehaviors>
</behaviors>
<bindings>
<wsHttpBinding>
<binding name="MyBinding" maxBufferPoolSize="1000000000" maxReceivedMessageSize="1000000000" messageEncoding="Mtom">
<security mode="Message">
<message clientCredentialType="UserName" />
</security>
</binding>
</wsHttpBinding>
</bindings>
<services>
<service behaviorConfiguration="MyBehavior" name="MyServiceName">
<endpoint address="" binding="wsHttpBinding" contract="MyWcfNamespaceOfMyDLL.IMyServiceName" bindingConfiguration="MyBinding">
<identity>
<dns value="localhost" />
</identity>
</endpoint>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
</service>
</services>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
</system.serviceModel>
</configuration>
This is my svc file inside web site root:
<%# ServiceHost Language="C#" Debug="true" Service="MyWcfNamespaceOfMyDLL.MyServiceName" %>
Finally, service contrat inside my dll appears like this:
[ServiceContract]
public interface IMyService
{
[OperationContract(ProtectionLevel=System.Net.Security.ProtectionLevel.EncryptAndSign)]
string DoSomething();
}
public class MyServiceName : IMyService
{
public string DoSomething();
}
public class MyValidator : UserNamePasswordValidator
{
// simple validation
}
Any idea?

I've solved.
The problem was about dll name missing on web config.
I had to change my config as following:
First:
<userNameAuthentication userNamePasswordValidationMode="Custom"
customUserNamePasswordValidatorType="="MyWcfNamespaceOfMyDLL.MyCustomValidator", MyDllName" />
Second:
<services>
<service behaviorConfiguration="MyBehavior"
name="MyWcfNamespaceOfMyDLL.MyServiceName">
<endpoint address="" binding="wsHttpBinding"
contract="IMyServiceName" bindingConfiguration="MyBinding">
<identity>
I think everyone could begin crazy..!!
Well, as you can see, I had to:
Specify DLL name on userNameAuthentication tag.
Specify namespace name on attribute name of service tag.
Remove specification about namespace name on contract attribute of endpoint tag.
Ok I 've solved, but I'm a bit worried for the next future ..!!

Are you sure that the problem comes from the service and not from the client ?
Can you show us how do you call this service ?
the request of message must be protected, such as required by a contract operation ('IMyService','http://tempuri.org/'). The
protection must be implemented by
('BasicHttpBinding','http://tempuri.org/') binding.
As said here,
If the binding does not support security (such as BasicHttpBinding),
the effective System.Net.Security.ProtectionLevel is
ProtectionLevel.None for the whole contract. The result is that
depending upon the endpoint binding, clients can require different
message or transport level security protection even when the contract
specifies ProtectionLevel.None.
This error message suggests you are calling the service with a basicHttpBinding with no ProtectionLevel.
Also, the contract in your Web.config IMyServiceName is not the same that in your code 'IMyService' or in the error message.

Related

Same WCF service with different EndPoints and Different Bindings For HTTPS

I have looked at several posts on SO which are showing how to add multiple endpoints for same service, but non of them is actually using HTTPS, which is why I am asking this question.
What I have
I have a web service,
https://portal.gov.com/us/216/_vti_bin/external/gov.svc
What I want
I want to call this web services using two different configurations, and bindings with different ENDPOINTS but SAME URL ?. (Sorry maybe I am confused with concept of EndPoints)
Here is what my web.config looks like,
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<configuration>
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior name="Gov_ServiceBehavior">
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="true" />
</behavior>
</serviceBehaviors>
<endpointBehaviors>
<behavior name="restBehavior">
<webHttp defaultBodyStyle="Wrapped" defaultOutgoingResponseFormat="Json" automaticFormatSelectionEnabled="true" />
</behavior>
</endpointBehaviors>
</behaviors>
<bindings>
<webHttpBinding>
<binding name="Gov_webHttpBinding">
<security mode="Transport">
<transport clientCredentialType="InheritedFromHost" />
</security>
</binding>
</webHttpBinding>
<!--<basicHttpBinding>
<binding name="Gov_BasicHttpBinding">
<security mode="Transport">
<transport clientCredentialType="InheritedFromHost" />
</security>
</binding>
</basicHttpBinding>-->
</bindings>
<services>
<service name="Portal.WebServices.External.Gov" behaviorConfiguration="Gov_ServiceBehavior">
<endpoint address="" binding="webHttpBinding" behaviorConfiguration="restBehavior" contract="Portal.WebServices.External.IGov" bindingConfiguration="Gov_webHttpBinding"/>
<endpoint address="mex" binding="mexHttpsBinding" contract="IMetadataExchange"/>
<!--<endpoint address="basic" binding="basicHttpBinding" contract="Portal.WebServices.External.IGov" bindingConfiguration="Gov_BasicHttpBinding"/>-->
</service>
</services>
</system.serviceModel>
</configuration>
WHERE IS THE PAIN
IT only works until I keep basicHttpBinding commented out and it's endpoint, as soon as I include it, I get silent error.
According to this - https://msdn.microsoft.com/en-us/library/ms751515(v=vs.110).aspx
It should work, but it doesn't maybe because I am using HTTPS and adding BINDINGS tag to my web.Config
What you are trying to achieve is impossible. You can't apply two different bindings with exactly the same Endpoint. If you try to read again your reference here it is clear that the sample has two different endpoints :
First address is http://localhost/servicemodelsamples/service.svc and the second
is http://localhost/servicemodelsamples/service.svc/secure. These two endpoints are different to each other but share with same contract.
The second endpoint is just relative to the base address http://localhost/servicemodelsamples/service.svc.
I hope this make your mind clear about binding and endpoint.

Net TCP binding: The URI prefix is not recognized

This really is bugging me for a couple of hours. I created the simplest WCF service using a TCP binding.
namespace WcfTcpService
{
public class TestTcpService : ITestTcpService
{
public string Hello(string name)
{
return "Hello, " + name + "!";
}
}
}
namespace WcfTcpService
{
[ServiceContract]
public interface ITestTcpService
{
[OperationContract]
string Hello(string name);
}
}
Web.config file has the following section:
<system.serviceModel>
<services>
<service name="WcfTcpService.TestTcpService" behaviorConfiguration="TestServiceBehavior">
<host>
<baseAddresses>
<add baseAddress="net.tcp://localhost:808/WcfTcpService.TestTcpService" />
</baseAddresses>
</host>
<endpoint address="" binding="netTcpBinding" bindingConfiguration="tcpBinding" contract="WcfTcpService.ITestTcpService"></endpoint>
<endpoint address="mex" binding="mexTcpBinding" bindingConfiguration="" contract="IMetadataExchange"></endpoint>
</service>
</services>
<bindings>
<netTcpBinding>
<binding name="tcpBinding" portSharingEnabled="true">
<security mode="None"></security>
</binding>
</netTcpBinding>
</bindings>
<behaviors>
<serviceBehaviors>
<behavior name="TestServiceBehavior">
<!-- To avoid disclosing metadata information, set the values below to false before deployment -->
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="true"/>
<!-- To receive exception details in faults for debugging purposes, set the value below to true. Set to false before deployment to avoid disclosing exception information -->
<serviceDebug includeExceptionDetailInFaults="false"/>
</behavior>
</serviceBehaviors>
</behaviors>
<!--<protocolMapping>
<add binding="basicHttpsBinding" scheme="https" />
<add binding="netTcpBinding" scheme="net.tcp" />
</protocolMapping>-->
<!--<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />-->
</system.serviceModel>
This service is hosted in IIS:
Now, when trying to add a reference to net.tcp://localhost:808/WcfTcpService.TestTcpService from a client application, I keep receiving the error:
The URI prefix is not recognized.
Metadata contains a reference that cannot be resolved: 'net.tcp://localhost/WcfTcpService.TestTcpService'.
The message could not be dispatched because the service at the endpoint address 'net.tcp://localhost/WcfTcpService.TestTcpService' is unavailable for the protocol of the address.
If the service is defined in the current solution, try building the solution and adding the service reference again.
The net.tcp service is running, I receive the same error with WcfTestClient.exe. and I can succesfully run http://localhost/WcfTcpService/TestTcpService.svc.
I've searched google but nothing came up.
Thanks!
EDIT:
The bindings screen of the 'Default Web site' looks like this btw:
When you create service that uses netTcpBinding and you want to Add service reference in Visual Studio you should use http address (httpGetEnabled) not actual tcp address the service listens on. So the solution was to set localhost/WcfTcpService/TestTcpService.svc as an url in Add service reference dialog.
I had same problem and I changed web.config as below:
<serviceHostingEnvironment multipleSiteBindingsEnabled="true">
<baseAddressPrefixFilters>
<add prefix="net.tcp://YourBaseUrl"/>
</baseAddressPrefixFilters>
</serviceHostingEnvironment>

Could not find a base address that matches scheme net.tcp for the endpoint

I have a Wcf Service project. system.serviceModel tag in my web.config is :
<system.serviceModel>
<bindings>
<netTcpBinding>
<binding name="RCISPNetTcpBinding" openTimeout="00:10:00" sendTimeout="00:10:00">
<security mode="Transport">
<transport clientCredentialType="Windows" protectionLevel="EncryptAndSign">
</transport>
<message clientCredentialType="Windows"/>
</security>
</binding>
</netTcpBinding>
</bindings>
<services>
<service behaviorConfiguration="RCISP.WcfServiceBehaviour" name="RCISP.WcfService.PersonWcfService">
<endpoint address="PersonServices" binding="netTcpBinding" bindingConfiguration="RCISPNetTcpBinding"
contract="RCISP.Common.ServiceContract.IPersonService" >
<identity>
<dns value="localhost" />
</identity>
</endpoint>
<host>
<baseAddresses>
<add baseAddress="net.tcp://localhost:40003/"/>
</baseAddresses>
</host>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="RCISP.WcfServiceBehaviour">
<serviceMetadata httpGetEnabled="false" />
<serviceDebug includeExceptionDetailInFaults="false" />
<serviceAuthorization principalPermissionMode="UseWindowsGroups" />
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
I have a runtime error when I want create self-hosting for service.
public class ServiceFactory : ServiceHostFactory
{
protected override ServiceHost CreateServiceHost(Type serviceType, Uri[] baseAddresses)
{
if (!IsInitialised) InitialiseService();
return base.CreateServiceHost(serviceType, baseAddresses);
}
}
Message of Exception is :
Could not find a base address that matches scheme net.tcp for the endpoint with binding NetTcpBinding. Registered base address schemes are [http].
Why?
You said you were self hosting the service (within your own process) but based on the code above I think you're trying to host it inside of a web application. If so Visual Studio's web server can not host a net.tcp end point. You'll need to set the project up to run under IIS. Please follow the instructions here .
If you are truly self hosting than you can leave the configuration exactly how you have it and spin up the service using the following code:
var host = new ServiceHost(typeof(Service1));
host.Open();
You need to add a protocol mapping to your configuration file to tell it what the "net.tcp" protocol is. Right after your <bindings> section add this:
<protocolMapping>
<add scheme="net.tcp" binding="netTcpbinding"/>
</protocolMapping>

WCF 4 Service with REST/SOAP endpoints in IIS 7.5

Hello and thank you for reading.
I'm trying to get a service hosted in IIS 7.5, that has multiple endpoints exposed.
I have a feeling the problem lies within my web.config, but I'll post my service code in here. There's no interface file, as I'm using the newer features of WCF 4, there's also no .svc file.
All the routing, from my understanding is handled in Global.asax.cs using the RouteTable feature.
Regardless, onto the code / config -
[ServiceContract]
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall)]
// NOTE: If the service is renamed, remember to update the global.asax.cs file
public class Service1
{
// TODO: Implement the collection resource that will contain the SampleItem instances
[WebGet(UriTemplate = "HelloWorld")]
public string HelloWorld()
{
// TODO: Replace the current implementation to return a collection of SampleItem instances
return "Hello World!";
}
}
And now, the config with the changes I thought would need to be made (I'm not sure if I needed to keep the standardEndpoints block, but with or without it I'm still getting error messages. -
<services>
<service name="AiSynthDocSvc.Service1" behaviorConfiguration="HttpGetMetadata">
<endpoint name="rest"
address=""
binding="webHttpBinding"
contract="AiSynthDocSvc.Service1"
behaviorConfiguration="REST" />
<endpoint name="soap"
address="soap"
binding="basicHttpBinding"
contract="AiSynthDocSvc.Service1" />
<endpoint name="mex"
address="mex"
binding="mexHttpBinding"
contract="IMetadataExchange" />
</service>
</services>
<behaviors>
<endpointBehaviors>
<behavior name="REST">
<webHttp/>
</behavior>
</endpointBehaviors>
<serviceBehaviors>
<behavior name="HttpGetMetadata">
<serviceMetadata httpGetEnabled="true" />
</behavior>
</serviceBehaviors>
</behaviors>
<standardEndpoints>
<webHttpEndpoint>
<!--
Configure the WCF REST service base address via the global.asax.cs file and the default endpoint
via the attributes on the <standardEndpoint> element below
-->
<standardEndpoint name="" helpEnabled="true" automaticFormatSelectionEnabled="true"/>
</webHttpEndpoint>
</standardEndpoints>
The Global.asax.cs file was left alone.
Again I'm pretty sure it has something to do with my config. The error I'm getting when I try to access any of the endpoints defined is -
The endpoint at '' does not have a Binding with the None MessageVersion. 'System.ServiceModel.Description.WebHttpBehavior' is only intended for use with WebHttpBinding or similar bindings.
Anyone have any ideas on this one?
Thanks,
Zachary Carter
OK, I tried to replicate your stuff - works like a charm for me :-)
I used your service class - no changes
I used your RegisterRoutes call in global.asax.cs
When I launch the web app from within Visual Studio, I get Cassini (the built-in web server) come up on http://localhost:3131/ - this might wary in your case.
Now, I can easily navigate there with a second browser window, and I do get a simple response on this URL:
http://localhost:3131/Service1/HelloWorld
+--------------------+
from Cassini
+--------+
name (first param) in ServiceRoute registration
+-----------+
from your URI template on the WebGet attribute
Does the same URL work for you??
Update: here's my config - I can connect to http://localhost:3131/Service1/HelloWorld in the browser using REST, and I can connect to http://localhost:3131/Service1/soap with the WCF Test Client to make a SOAP call (my Service1 lives in the RestWebApp namespace - thus my service and contract names are a tad different than yours - but other than that, I believe it's identical to your own config):
<system.serviceModel>
<serviceHostingEnvironment
aspNetCompatibilityEnabled="true" />
<services>
<service name="RestWebApp.Service1" behaviorConfiguration="Meta">
<endpoint name="rest"
address=""
binding="webHttpBinding"
contract="RestWebApp.Service1"
behaviorConfiguration="REST" />
<endpoint name="SOAP"
address="soap"
binding="basicHttpBinding"
contract="RestWebApp.Service1" />
<endpoint name="mex"
address="mex"
binding="mexHttpBinding"
contract="IMetadataExchange" />
</service>
</services>
<behaviors>
<endpointBehaviors>
<behavior name="REST">
<webHttp/>
</behavior>
</endpointBehaviors>
<serviceBehaviors>
<behavior name="Meta">
<serviceMetadata httpGetEnabled="true" />
</behavior>
</serviceBehaviors>
</behaviors>
<standardEndpoints>
<webHttpEndpoint>
<!--
Configure the WCF REST service base address via the global.asax.cs file and the default endpoint
via the attributes on the <standardEndpoint> element below
-->
<standardEndpoint name="" helpEnabled="true" automaticFormatSelectionEnabled="true"/>
</webHttpEndpoint>
</standardEndpoints>
</system.serviceModel>
Thanks for this it helped me a lot.
The issue in my case was that I had a default behaviour configured that contains webHttp. After giving it the name="REST" and setting my webHttpBinding endpoint behaviourConfiguration ="REST" I had no further errors.
<system.serviceModel>
<bindings>
<customBinding>
<binding name="CustomBinding_IMobileService">
<binaryMessageEncoding />
<httpTransport />
</binding>
</customBinding>
</bindings>
<client>
<endpoint address="http://localhost:6862/silverlight/services/MobileService.svc"
binding="customBinding" bindingConfiguration="CustomBinding_IMobileService"
contract="AlchemyMobileService.IMobileService" name="CustomBinding_IMobileService" />
</client>
<services>
<service name="MobileService.Alchemy">
<endpoint address="http://localhost:8732/mobileservice" binding="webHttpBinding" contract="MobileService.IAlchemy" behaviorConfiguration="REST">
</endpoint>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior>
<serviceDebug includeExceptionDetailInFaults="True" />
</behavior>
</serviceBehaviors>
<endpointBehaviors>
<behavior name="REST">
<webHttp />
</behavior>
</endpointBehaviors>
</behaviors>

getting error message related to basicHttpBinding even though I'm using wsHttpBinding

I am trying to expose a WCF service at a wsHttpBinding endpoint and it gives me the following error message :
Contract requires Session, but Binding
'BasicHttpBinding' doesn't support it
or isn't configured properly to
support it.
Here is the interface :
[ServiceContract(Namespace="http://server.com/orderservices/",SessionMode=SessionMode.Required)]
public interface IOrderService
{
[OperationContract(IsInitiating=true,IsTerminating=false)]
string GetOrderNumber();
[OperationContract(IsInitiating = false, IsTerminating = true)]
void CreateOrder(string orderXML);
}
Here is my web.config file (the service is hosted in IIS 7 ) :
<system.serviceModel>
<bindings>
<wsHttpBinding>
<binding name="longTimeoutBinding"
receiveTimeout="00:10:00" sendTimeout="00:10:00">
</binding>
</wsHttpBinding>
</bindings>
<services>
<service name="eMidWare.OrderService">
<host>
<baseAddresses>
<add baseAddress = "http://localhost/" />
</baseAddresses>
</host>
<!-- Service Endpoints -->
<endpoint
address=""
binding="wsHttpBinding" bindingConfiguration="longTimeoutBinding"
contract="eMidWare.IPricingDataService">
</endpoint>
<endpoint
address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior>
<serviceDebug includeExceptionDetailInFaults="True" />
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
Hmmm.... check your service contract - it's a IOrderService
[ServiceContract(Namespace="http://server.com/orderservices/",SessionMode=SessionMode.Required)]
public interface IOrderService
{
}
but in your config, you're setting up an endpoint for eMidWare.IPricingDataService
<endpoint
address=""
binding="wsHttpBinding" bindingConfiguration="longTimeoutBinding"
contract="eMidWare.IPricingDataService">
Therefore, I believe, .NET / WCF 4 will kick in a default endpoint, which is of basicHttpBinding for the http:// scheme by default....
If you had posted your service interface I could have said with certainty but I believe you have something like this on your service interface:
[ServiceContract(SessionMode = SessionMode.Required)]
This would require session and BasicHttpBinding does not support it. You need to use wsHttpBinding if you need to have sessions.

Categories

Resources