WCF REST WebInvoke POST returns bad response - vb.net

May anybody help me I am tired of doing all the thing, but service returns bad return if string length exceeds more than 10000 characters.
Thanks.
This is my .svc file:
<%# ServiceHost Language="VB" Debug="true" Service="BPMMobile"
CodeBehind="~/App_Code/BPMMobile.svc.vb" Factory="MyServiceHostFactory" %>
My contract:
<OperationContract()> _
<WebInvoke(UriTemplate:="/SaveData?
Data={Data}", BodyStyle:=WebMessageBodyStyle.Bare, Method:="POST", ResponseFormat:=WebMessageFormat.Xml)> _
Function SaveData(Data As String) As String
Here is my web.config file:
<system.serviceModel>
<bindings>
<webHttpBinding>
<binding name="MobileBinding" maxReceivedMessageSize="5242880">
<readerQuotas maxDepth="32" maxStringContentLength="5242880" maxArrayLength="16384" maxBytesPerRead="4096" maxNameTableCharCount="16384" />
</binding>
</webHttpBinding>
</bindings>
<services>
<service name="BPMMobile">
<endpoint
behaviorConfiguration="webHttp"
binding="webHttpBinding"
bindingConfiguration="MobileBinding"
contract="IBPMMobile" />
</service>
<service name="DMSService">
<endpoint
behaviorConfiguration="webHttp"
binding="webHttpBinding"
contract="IDMSService" />
</service>
<service name="ImportMaster">
<endpoint
behaviorConfiguration="webHttp"
binding="webHttpBinding"
contract="IImportMaster" />
</service>
</services>
<behaviors>
<endpointBehaviors>
<behavior name="webHttp">
<webHttp />
</behavior>
</endpointBehaviors>
<serviceBehaviors>
<behavior name="">
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true" />
</behavior>
</serviceBehaviors>
</behaviors>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
</system.serviceModel>`
Here is my Custom service host
Public Class MyServiceHost
Inherits WebServiceHost
Public Sub New()
End Sub
Public Sub New(singletonInstance As Object, ParamArray baseAddresses As Uri())
MyBase.New(singletonInstance, baseAddresses)
End Sub
Public Sub New(serviceType As Type, ParamArray baseAddresses As Uri())
MyBase.New(serviceType, baseAddresses)
End Sub
Protected Overrides Sub OnOpening()
MyBase.OnOpening()
If MyBase.Description IsNot Nothing Then
For Each endpoint In MyBase.Description.Endpoints
Dim transport = endpoint.Binding.CreateBindingElements().Find(Of TransportBindingElement)()
If transport IsNot Nothing Then
transport.MaxReceivedMessageSize = 5242880
transport.MaxBufferPoolSize = 5242880
transport.MaxBufferPoolSize = 5242880
End If
Next
End If
End Sub
End Class
Class MyWebServiceHostFactory
Inherits WebServiceHostFactory
Protected Overrides Function CreateServiceHost(serviceType As Type, baseAddresses As Uri()) As ServiceHost
Return New MyServiceHost(serviceType, baseAddresses)
End Function
End Class
Public NotInheritable Class MyServiceHostFactory
Inherits System.ServiceModel.Activation.ServiceHostFactory
Public Overrides Function CreateServiceHost(constructorString As String, baseAddresses As Uri()) As System.ServiceModel.ServiceHostBase
Return MyBase.CreateServiceHost(constructorString, baseAddresses)
End Function
Protected Overrides Function CreateServiceHost(serviceType As Type, baseAddresses As Uri()) As System.ServiceModel.ServiceHost
Return New MyServiceHost(serviceType, baseAddresses)
End Function
End Class

Related

Configuring Web.config to publish WCF Service

I am making the jump from asmx webservice to WCF (mostly to support working with Json)
I have gotten to the point that the Service works (locally only) in http only but not https. (On my server neither works as the server forces https)
Here is my simple Codes:
MyNewService.VB
Public Class MyNewService
Implements IMyNewService
Public Sub New()
End Sub
Public Function GetResults() As List(Of Person) Implements IMyNewService.GetResults
Dim rslt As New List(Of Person)
rslt.Add(New Person("Mike", "Anderson", 40))
rslt.Add(New Person("Drew", "Carry", 38))
rslt.Add(New Person("John", "Tavares", 43))
Return rslt
End Function
End Class
IMyNewService.VB
<ServiceContract()>
Public Interface IMyNewService
<OperationContract()>
<WebInvoke(Method:="GET", RequestFormat:=WebMessageFormat.Json, ResponseFormat:=WebMessageFormat.Json, UriTemplate:="getPeople")>
Function GetResults() As List(Of Person)
End Interface
<DataContract()>
Public Class Person
<DataMember()>
Public Property FirstName() As String
<DataMember()>
Public Property LastName() As String
<DataMember()>
Public Property Age() As Integer
Public Sub New(firstname As String, lastname As String, age As Integer)
Me.FirstName = firstname
Me.LastName = lastname
Me.Age = age
End Sub
End Class
Web.Config
<?xml version="1.0"?>
<configuration>
<appSettings>
<add key="aspnet:UseTaskFriendlySynchronizationContext" value="true" />
</appSettings>
<system.web>
<compilation debug="true" strict="false" explicit="true" targetFramework="4.7.2" />
<httpRuntime targetFramework="4.7.2"/>
<pages>
<namespaces>
<add namespace="System.Runtime.Serialization" />
<add namespace="System.ServiceModel" />
<add namespace="System.ServiceModel.Web" />
</namespaces>
</pages>
</system.web>
<system.serviceModel>
<protocolMapping>
<add scheme="http" binding="webHttpBinding"/>
</protocolMapping>
<behaviors>
<serviceBehaviors>
<behavior>
<!-- To avoid disclosing metadata information, set the value below to false and remove the metadata endpoint above before deployment -->
<serviceMetadata httpGetEnabled="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>
<endpointBehaviors>
<behavior>
<webHttp/>
</behavior>
</endpointBehaviors>
</behaviors>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
</system.serviceModel>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true"/>
<!--
To browse web app root directory during debugging, set the value below to true.
Set to false before deployment to avoid disclosing web app folder information.
-->
<directoryBrowse enabled="true"/>
</system.webServer>
</configuration>
So, currently I can run:
http://localhost:61028/MyNewService.svc/getPeople
and I correctly get :
[{"Age":40,"FirstName":"Yoni","LastName":"Sudwerts"},{"Age":38,"FirstName":"Joshua","LastName":"Kishinef"},{"Age":43,"FirstName":"Saul","LastName":"Kaye"}]
But if I run:
https://localhost:44386/MyNewService.svc/getPeople
I get a 404 Error.
Can anyone find my mistake and help a guy out?
Thanks in advance
Generally speaking, I add two service endpoint address to host the service over http and https.
WCF Service not hitting from postman over https
Or the following simplified configuration.
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior>
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="true"/>
<serviceDebug includeExceptionDetailInFaults="false"/>
</behavior>
</serviceBehaviors>
<endpointBehaviors>
<behavior>
<webHttp />
</behavior>
</endpointBehaviors>
</behaviors>
<bindings>
<webHttpBinding>
<binding name="https">
<security mode="Transport">
<transport clientCredentialType="None"></transport>
</security>
</binding>
</webHttpBinding>
</bindings>
<protocolMapping>
<add binding="webHttpBinding" scheme="http" />
<add binding="webHttpBinding" scheme="https" bindingConfiguration="https" />
</protocolMapping>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
Feel free to let me know if there is anything I can help with.

crossdomain.xml on WCF Service hosted by Windows Service

I am trying to make my Windows Service, which hosts a WCF service cross-domain compatible.
After hours and hours of searching I was told that I needed to create another service which will load the crossdomain.xml and clientaccesspolicy.xml files so that the Windows hosted WCF service can be run on any domain.
This is my main service :
Namespace UmbrellaMobileService
<RunInstaller(True)> _
Public Class ProjectInstaller
Inherits Installer
Private process As ServiceProcessInstaller
Private service As ServiceInstaller
Private components As System.ComponentModel.Container
Public Sub New()
process = New ServiceProcessInstaller()
process.Account = ServiceAccount.LocalSystem
service = New ServiceInstaller()
service.ServiceName = "UmbrellaMobileService"
service.DisplayName = "Umbrella Mobile Service"
service.Description = "Handels Umbrella Mobile Requests."
Installers.Add(process)
Installers.Add(service)
End Sub
End Class
<ServiceBehavior(InstanceContextMode:=InstanceContextMode.PerSession)> _
Public Class UmbrellaMobileService
Inherits ServiceBase
Public serviceHost As ServiceHost = Nothing
Public CrossDomainServiceHost As ServiceHost = Nothing
Public Shared Sub Main()
ServiceBase.Run(New UmbrellaMobileService())
End Sub
Public Sub New()
ServiceName = "UmbrellaMobileService"
End Sub
'Start the Windows service.
Protected Overloads Overrides Sub OnStart(ByVal args As String())
If serviceHost IsNot Nothing Then
serviceHost.Close()
End If
serviceHost = New WebServiceHost(GetType(UmbrellaService), New Uri("http://localhost/UmbrellaMobileService"))
serviceHost.AddServiceEndpoint(GetType(IUmbrellaMobileService), New WebHttpBinding(), "http://localhost/UmbrellaMobileService")
CrossDomainServiceHost = New ServiceHost(GetType(CrossDomainService))
Else
System.Diagnostics.EventLog.WriteEntry("Umbrella Mobile Service", objIniFile.ErrorMessage, EventLogEntryType.Error)
serviceHost.Close()
CrossDomainServiceHost.Close()
End If
serviceHost.Open()
CrossDomainServiceHost.Open()
End Sub
' Stop the Windows service.
Protected Overloads Overrides Sub OnStop()
If serviceHost IsNot Nothing Then
serviceHost.Close()
CrossDomainServiceHost.Close()
serviceHost = Nothing
End If
End Sub
End Class
<AspNetCompatibilityRequirements(Requirementsmode:=AspNetCompatibilityRequirementsMode.Allowed)> _
Public Class UmbrellaService
Inherits System.Web.Services.WebService
Implements IUmbrellaMobileService
Function GetCustomers() As Stream Implements IUmbrellaMobileService.GetCustomers
'Function Logic
End Function
End Class
End Namespace
This is my Implementation of my main service:
Namespace UmbrellaMobileService
<ServiceContract()> _
Public Interface IUmbrellaMobileService
<OperationContract()> _
<WebInvoke(Method:="GET", BodyStyle:=WebMessageBodyStyle.Bare, ResponseFormat:=WebMessageFormat.Json, RequestFormat:=WebMessageFormat.Json)> _
Function GetCustomers() As Stream
End Interface
End Namespace
This is the 'Cross Domain Service' I was advised to add:
Namespace UmbrellaMobileService
Public Class CrossDomainService
Implements ICrossDomainService
Public Function ProvidePolicyFile() As System.ServiceModel.Channels.Message Implements ICrossDomainService.ProvidePolicyFile
Dim filestream As FileStream = File.Open("ClientAccessPolicy.xml", FileMode.Open)
' Either specify ClientAccessPolicy.xml file path properly
' or put that in \Bin folder of the console application
Dim reader As XmlReader = XmlReader.Create(filestream)
Dim result As System.ServiceModel.Channels.Message = Message.CreateMessage(MessageVersion.None, "", reader)
Return result
End Function
End Class
End Namespace
And here is its Implementation :
Namespace UmbrellaMobileService
<ServiceContract()> _
Public Interface ICrossDomainService
<OperationContract(), WebGet(UriTemplate:="ClientAccessPolicy.xml")> _
Function ProvidePolicyFile() As Message
End Interface
End Namespace
My config file looks like this :
<?xml version="1.0"?>
<configuration>
<system.serviceModel>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true"/>
<behaviors>
<serviceBehaviors>
<behavior name="MyServiceBehavior">
<serviceMetadata httpGetEnabled="true"/>
<serviceDebug includeExceptionDetailInFaults="false"/>
</behavior>
</serviceBehaviors>
<endpointBehaviors>
<behavior name="CrossDomainServiceBehavior">
<webHttp/>
</behavior>
</endpointBehaviors>
</behaviors>
<services>
<service behaviorConfiguration="MyServiceBehavior" name="UmbrellaMobileService.UmbrellaMobileService">
<endpoint address="" binding="basicHttpBinding" contract="UmbrellaMobileService.IUmbrellaMobileService">
</endpoint>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
<host>
<baseAddresses>
<add baseAddress="http://localhost:8731/UmbrellaMobileService"/>
</baseAddresses>
</host>
</service>
<service name="UmbrellaMobileService.CrossDomainService">
<host>
<baseAddresses>
<add baseAddress="http://localhost:8731/"/>
</baseAddresses>
</host>
<endpoint address="" binding="webHttpBinding" contract="UmbrellaMobileService.ICrossDomainService" behaviorConfiguration="CrossDomainServiceBehavior"/>
</service>
</services>
</system.serviceModel>
<system.web>
<compilation debug="true"/></system.web></configuration>
Now, I get this error when I attempt to run this service:
Service cannot be started. System.InvalidOperationException: Service has zero application (non-infrastructure) endpoints.
This might be because no configuration file was found for your application,
or because no service element matching the service name could be found in the configuration file, or because no endpoints were defined in the service element.
I have searched and searched and still do not know what to do, can anyone give me some advice?
I had the same issue and here is how I fixed it.
First, create a new service class that will serve up the clientaccesspolicy.xml when a client requests it:
[ServiceContract]
public class CrossDomainPolicyService
{
private Stream StringToStream(string result)
{
WebOperationContext.Current.OutgoingResponse.ContentType = "application/xml";
return new MemoryStream(Encoding.UTF8.GetBytes(result));
}
[OperationContract, WebGet(UriTemplate = "/clientaccesspolicy.xml")]
public Stream GetClientAccessPolicy()
{
string result = #"<?xml version=""1.0"" encoding=""utf-8""?>
<access-policy>
<cross-domain-access>
<policy>
<allow-from http-request-headers=""*"">
<domain uri=""*""/>
</allow-from>
<grant-to>
<resource path=""/"" include-subpaths=""true""/>
</grant-to>
</policy>
</cross-domain-access>
</access-policy>";
return StringToStream(result);
}
}
Next, modify your app.config file to expose the new service:
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior name="">
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true" />
</behavior>
</serviceBehaviors>
<endpointBehaviors>
<behavior name="policyBehavior">
<webHttp />
</behavior>
</endpointBehaviors>
</behaviors>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
<services>
<service name="MyNamespace.MyService">
<endpoint address="" binding="basicHttpBinding" contract="MyNamespace.IMyService">
<identity>
<dns value="localhost" />
</identity>
</endpoint>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
<host>
<baseAddresses>
<add baseAddress="http://localhost:9876/MyService/" />
</baseAddresses>
</host>
</service>
<service name="MyNamespace.CrossDomainPolicyService">
<endpoint address="" binding="webHttpBinding" contract="MyNamespace.CrossDomainPolicyService" behaviorConfiguration="policyBehavior">
<identity>
<dns value="localhost" />
</identity>
</endpoint>
<host>
<baseAddresses>
<!-- Root Domain where the other service is hosted -->
<add baseAddress="http://localhost:9876/" />
</baseAddresses>
</host>
</service>
</services>
</system.serviceModel>
... and that should do it!

WCF restful service, server did not provide a meaningful reply

I am creating a restful service using WCF, I keep getting the error:
The server did not provide a meaningful reply; this might be caused by a contract mismatch, a premature session shutdown or an internal server error.
It is a time clock application, which takes in the username and the current time and stores it in a database for logging in/out.
I am new to the REST world can anyone help me?
My service interface:
ServiceContract(Namespace:="WCFRESTService")> _
Public Interface IService1
<OperationContract()> _
<WebInvoke(UriTemplate:="/login", Method:="PUT")> _
Function InsertUserDetails(ByVal username As String, ByVal time As DateTime) As String
End Interface
Service code:
<AspNetCompatibilityRequirements(RequirementsMode:=AspNetCompatibilityRequirementsMode.Required)> _
<ServiceBehavior(Namespace:="WCFRESTService")> _
Public Class Service1
Implements IService1
Private con As New SqlConnection("Data Source=TE-LAPTOP-001\SQL2008R2;Initial Catalog=timeClock;Integrated Security=True")
Public Function InsertUserDetails(ByVal username As String, ByVal time As DateTime) As String Implements IService1.InsertUserDetails
Dim strMessage As String = String.Empty
Dim errorMessage As String = String.Empty
Dim numcount As Integer = 0
numcount = getusercount(username)
If (numcount = 0) Then
Try
con.Open()
Dim cmd As New SqlCommand("spInsertLog", con)
cmd.CommandType = CommandType.StoredProcedure
cmd.Parameters.AddWithValue("#username", username)
cmd.Parameters.AddWithValue("#timein", time)
cmd.ExecuteNonQuery()
Catch ex As Exception
errorMessage = ex.ToString
Finally
con.Close()
End Try
strMessage = "You have Signed In at: " + time
ElseIf (numcount = 1) Then
strMessage = "Error: You need to SignOut before you can SignIn"
End If
Return errorMessage + strMessage
End Function
Public Function getusercount(ByVal username As String) As Integer
Dim count As Int32 = 0
Try
con.Open()
Dim cmd As New SqlCommand("spgetcount", con)
cmd.CommandType = CommandType.StoredProcedure
cmd.Parameters.AddWithValue("#username", username)
count = Convert.ToInt32(cmd.ExecuteScalar())
Catch ex As Exception
Finally
con.Close()
End Try
Return count
End Function
End Class
My client code
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Dim objervice As New ServiceReference1.Service1Client()
Dim result As String = objervice.InsertUserDetails("User1", DateTime.Now)
MsgBox(result)
End Sub
Service webconfig:
<system.serviceModel>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true"/>
<services>
<service name="WcfRESTService1.Service1" behaviorConfiguration="WcfRESTService1.Service1Behavior">
<!-- Service Endpoints -->
<endpoint address="http://localhost:62131/Service1.svc" binding="webHttpBinding" contract="WcfRESTService1.IService1" behaviorConfiguration="web">
<!--
Upon deployment, the following identity element should be removed or replaced to reflect the
identity under which the deployed service runs. If removed, WCF will infer an appropriate identity
automatically.
-->
<identity>
<dns value="localhost"/>
</identity>
</endpoint>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="WcfRESTService1.Service1Behavior">
<!-- To avoid disclosing metadata information, set the value below to false and remove the metadata endpoint above before deployment -->
<serviceMetadata httpGetEnabled="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>
<endpointBehaviors>
<behavior name="web">
<webHttp/>
</behavior>
</endpointBehaviors>
</behaviors>
</system.serviceModel>
Client config:
<system.serviceModel>
<bindings>
<customBinding>
<binding name="WebHttpBinding_IService1">
<textMessageEncoding maxReadPoolSize="64" maxWritePoolSize="16"
messageVersion="Soap12" writeEncoding="utf-8">
<readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384"
maxBytesPerRead="4096" maxNameTableCharCount="16384" />
</textMessageEncoding>
<httpTransport/>
</binding>
</customBinding>
</bindings>
<client>
<endpoint address="http://localhost:62131/Service1.svc" binding="customBinding" bindingConfiguration="WebHttpBinding_IService1"
contract="ServiceReference1.IService1" name="WebHttpBinding_IService1" />
</client>
<behaviors>
<endpointBehaviors>
<behavior name="test">
<webHttp />
</behavior>
</endpointBehaviors>
</behaviors>
</system.serviceModel>
You don't need REST here (for such kind of client).
But if you want - try use stream for WebGet-responding from from REST method:
[OperationContract, WebGet(UriTemplate = "/SendMessage?login={login}&password={password}&phoneNum={phoneNum}&message={message}", BodyStyle = WebMessageBodyStyle.Bare, ResponseFormat = WebMessageFormat.Json)]
System.IO.Stream SendMessage(string login, string password, string phoneNum, string message, TimeSpan timeout);
//..
public Stream SendMessage(string login, string password, string phoneNum, string message, TimeSpan timeout)
{
//..
return new MemoryStream(Encoding.Default.GetBytes(jsonString));
}

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.

Securing WCF service endpoint with custom authentication

I want to secure some endpoint of a WCF service, i dont know if you can secure some endpoint and some not. Below I have the stripped WCF service (self hosted). The same WCF serves also the CA Policy file. If I secure this WCF service or some endpoints of ut the CA Policy part must not ask me a username password. The policy file must be accessible all the time. Is that also possible?
I found alot WCF custom blogs/postings. There are alot of ways to do security. All I want is that I can secure some endpoints with username/password but the credentials must not be visible with tools like Fiddler. The data however it can be visible in this case.
I implemented already a Customvalidator but the app.config file is also importent to define things. And I am not very good at that.
namespace WindowsFormsApplication11
{
public partial class Form1 : Form
{
public ServiceHost _host = null;
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
// Create a ServiceHost for the CalculatorService type and
// provide the base address.
_host = new ServiceHost(typeof(WmsStatService));
_host.AddServiceEndpoint(typeof(IPolicyProvider), new WebHttpBinding(), "").Behaviors.Add(new WebHttpBehavior());
_host.Open();
}
}
// Define a service contract.
[ServiceContract(Namespace = "http://WindowsFormsApplication11")]
public interface IWmsStat
{
[OperationContract]
string getConnectedViewers(string channelName);
[OperationContract]
string sayHello(string name);
}
[ServiceContract]
public interface IPolicyProvider
{
[OperationContract, WebGet(UriTemplate = "/ClientAccessPolicy.xml")]
Stream ProvidePolicy();
}
//[DataContract]
public class Ads
{
// [DataMember]
public string AdFileName { get; set; }
//[DataMember]
public string AdDestenationUrl { get; set; }
public string ConnectedUserIP { get; set; }
}
//
public class CustomValidator : UserNamePasswordValidator
{
public override void Validate(string userName, string password)
{
if(null == userName || null == password)
{
throw new ArgumentNullException();
}
if(userName == "Oguz" && password == "2009")
{
return;
}
FaultCode fc = new FaultCode("ValidationFailed");
FaultReason fr = new FaultReason("Good reason");
throw new FaultException(fr,fc);
}
}
//
public class WmsStatService : IWmsStat, IPolicyProvider
{
public string sayHello(string name)
{
return "hello there " + name + " nice to meet you!";
}
public Stream ProvidePolicy()
{
WebOperationContext.Current.OutgoingResponse.ContentType = "application/xml";
return new MemoryStream(File.ReadAllBytes("ClientAccessPolicy.xml"), false);
}
public string getConnectedViewers(string channelname)
{
// do stuff
return null;
}
}
}
The app.config. This config file does not work. I wanted to put the custom authentication for a endpoint. I have no clue.
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.serviceModel>
<services>
<service name="WindowsFormsApplication11.WmsStatService" behaviorConfiguration="mex">
<host>
<baseAddresses>
<add baseAddress="http://192.168.0.199:87" />
</baseAddresses>
</host>
<endpoint address="http://192.168.0.199:87/Test" binding="basicHttpBinding" bindingConfiguration="" contract="WindowsFormsApplication11.IWmsStat" behaviorConfiguration="MyServiceBehavior" />
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
</service>
</services>
<!--<bindings>
<wsHttpBinding>
<binding name="wshttp">
<security mode="Message">
<message clientCredentialType="UserName" />
</security>
</binding>
</wsHttpBinding>
</bindings>-->
<behaviors>
<serviceBehaviors>
<behavior name="mex">
<serviceMetadata httpGetEnabled="true" httpGetUrl=""/>
</behavior>
<behavior name="MyServiceBehavior">
<serviceCredentials>
<userNameAuthentication userNamePasswordValidationMode="Custom" customUserNamePasswordValidatorType="WindowsFormsApplication11.CustomValidator, CustomValidator" />
</serviceCredentials>
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
</configuration>
I want to secure some endpoint of a
WCF service, i dont know if you can
secure some endpoint and some not.
Sure - you just need to create two separate binding configurations, and use one on those endpoints that are secured, the other on the others:
<bindings>
<basicHttpBinding>
<binding name="secured">
<security mode="Message">
<message ...... />
</security>
</binding>
<binding name="unsecured">
<security mode="None" />
</binding>
</basicHttpBinding>
</bindings>
<services>
<service name="WindowsFormsApplication11.WmsStatService" behaviorConfiguration="mex">
<host>
<baseAddresses>
<add baseAddress="http://192.168.0.199:87" />
</baseAddresses>
</host>
<endpoint address="/Secured/Test"
binding="basicHttpBinding" bindingConfiguration="secured"
contract="WindowsFormsApplication11.IWmsStat"
behaviorConfiguration="MyServiceBehavior" />
<endpoint address="/Unsecured/Test"
binding="basicHttpBinding" bindingConfiguration="unsecured"
contract="WindowsFormsApplication11.IWmsStat"
behaviorConfiguration="MyServiceBehavior" />
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
</service>
</services>
Marc
PS: not sure if that's just a problem with your postings not being up to date anymore - have you noticed, that you have two separate behavior configurations:
<behaviors>
<serviceBehaviors>
<behavior name="mex">
<serviceMetadata httpGetEnabled="true" httpGetUrl=""/>
</behavior>
<behavior name="MyServiceBehavior">
<serviceCredentials>
<userNameAuthentication
userNamePasswordValidationMode="Custom"
customUserNamePasswordValidatorType="WindowsFormsApplication11.CustomValidator, CustomValidator" />
</serviceCredentials>
</behavior>
</serviceBehaviors>
</behaviors>
and your service is only referencing the "mex" behavior? That means, your service is indeed using the <serviceMetadata> behavior - but NOT the <serviceCredentials> one!
You need to merge these into one and then reference just that:
<behaviors>
<serviceBehaviors>
<behavior name="Default">
<serviceMetadata httpGetEnabled="true" httpGetUrl=""/>
<serviceCredentials>
<userNameAuthentication
userNamePasswordValidationMode="Custom"
customUserNamePasswordValidatorType="WindowsFormsApplication11.CustomValidator, CustomValidator" />
</serviceCredentials>
</behavior>
</serviceBehaviors>
</behaviors>
<services>
<service name="...." behaviorConfiguration="Default"
Marc
If you want to protect entire message, Transport security mode is a way to go. If you want to only your headers to be encrypted/signed, Message security mode allows this, but you'll have to use wsHttpBinding. You may also consider using Digest to protect credentials.
As for your example, I think your commented part should look like this:
<bindings>
<basicHttpBinding>
<binding name="secure">
<security mode="Transport">
<transport clientCredentialType="Basic" />
</security>
</binding>
</basicHttpBinding>
</bindings>
You'll also have to update your endpoint declaration:
<endpoint
address="https://192.168.0.199:87/Test"
binding="basicHttpBinding" bindingConfiguration="secure"
contract="WindowsFormsApplication11.IWmsStat" />
You won't be allowed to use plain HTTP with transport security mode.