I am trying to setup a NetTCP WCF service.
This is my server code:
iSync.cs:
[ServiceContract]
public interface ISync
{
[OperationContract(IsOneWay = true)]
void UploadMotionDynamic(byte[] jpegStream, string alias, Int16 camIndex, byte[] motionLog, double mul, byte isLive, byte doIsave);
}
Sync.cs:
public class Sync : ISync
{
public void UploadMotionDynamic(byte[] jpegData, string alias, Int16 camIndex, byte[] motionLog,double mul,byte isLive, byte doIsave)
{
//do stuff
}
}
web.config:
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior name="NetTCPBehaviour">
<serviceDebug includeExceptionDetailInFaults="True" />
<dataContractSerializer maxItemsInObjectGraph="65536" />
</behavior>
</serviceBehaviors>
</behaviors>
<services>
<service name="Sync" behaviorConfiguration="NetTCPBehaviour">
<endpoint address="net.tcp://localhost:8888/Sync" binding="netTcpBinding" contract="ISync" name="wsSyncerMotion" bindingConfiguration="NetTCPBindingEndPoint"/>
</service>
</services>
<bindings>
<netTcpBinding>
<binding name="NetTCPBindingEndPoint" sendTimeout="00:01:00">
<security mode="None" />
</binding>
</netTcpBinding>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
</system.serviceModel>
Now it cannot be the port being blocked because I even tested it by turning off the firewall.
I have made sure 'Net Tcp Listener Adaptor' is running in my
services.
I have added net.tcp in my IIS\Advanced Settings| Enabled
Protocols.
I have added the Non-HTTP activation setting in .NET
Features.
I have followed the links kindly supplied by people here.
The error I get (now) is:
(I cannot seem to enlarge this image with viewing in a different tab)
Related
I have a WCF service created with VS2013 on Win8. If I start the service via VS (localhost:port) I'm able to do GET response in json
but same service i am hosted on server (IIS7) then i get 404 Error
localhost URL : http://localhost:43596/abc.svc/LoginUser/abc/abc
Live URL: http://mywwebsite.com:80/abc.svc/LoginUser/abc/abc
In my opionio, there might something amiss with the hosting environment, try to enable WCF feature support in IIS.
Here is my service, wish it is useful to you.
IService1.cs
[ServiceContract]
public interface IService1
{
[OperationContract]
[WebGet]
string GetData(int value);
Service1.svc.
public class Service1 : IService1
{
public string GetData(int value)
{
return string.Format("You entered: {0}", value);
}
Web.config
<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="mybinding">
<security mode="Transport">
<transport clientCredentialType="None"></transport>
</security>
</binding>
</webHttpBinding>
</bindings>
<protocolMapping>
<add binding="webHttpBinding" scheme="http"/>
<add binding="webHttpBinding" scheme="https" bindingConfiguration="mybinding"/>
</protocolMapping>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
</system.serviceModel>
Since the above configuration support both http and https protocol, we need to add http and https binding in IIS site binding module.
Reference.
How to make WCF Service Use HTTPS protocol
Feel free to let me know if there is anything I can help with.
I am attempting to secure a new .Net 4.5 WCF service using HTTPS / SSL, Basic client credentials and the WebHttpBinding. From reading up online I found a good series of Blog Posts from Allen Conway which I have used as a template.
WCF configuration
<system.serviceModel>
<bindings>
<webHttpBinding>
<binding name="webInteropSecureBinding" allowCookies="false" maxBufferPoolSize="2097152" maxBufferSize="2097152" maxReceivedMessageSize="2097152">
<security mode="Transport">
<transport clientCredentialType="Basic"></transport>
</security>
</binding>
</webHttpBinding>
</bindings>
<services>
<service name="PsmDataProvider.PsmProvider" behaviorConfiguration="SecureRest">
<clear />
<endpoint address="" binding="webHttpBinding" bindingConfiguration="webInteropSecureBinding" name="PsmProvider" contract="PsmDataProvider.IPsmProvider" behaviorConfiguration="webHttpBehavior" />
<endpoint address="mex" binding="mexHttpsBinding" name="mex" contract="IMetadataExchange" listenUriMode="Explicit" />
<host>
<baseAddresses>
<add baseAddress="https://localhost:44300/PsmProvider/" />
</baseAddresses>
</host>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="SecureRest">
<serviceMetadata httpGetEnabled="false" httpsGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true" />
<serviceCredentials>
<userNameAuthentication userNamePasswordValidationMode="Custom"
customUserNamePasswordValidatorType="PsmDataProvider.Security.CustomerUserNamePasswordValidator, PsmDataProvider"/>
</serviceCredentials>
</behavior>
</serviceBehaviors>
<endpointBehaviors>
<behavior name="webHttpBehavior">
<webHttp />
</behavior>
</endpointBehaviors>
</behaviors>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
</system.serviceModel>
CustomerUserNamePasswordValidator
I have stubbed out the CustomerUserNamePasswordValidator implementation and have confirmed that the constructor is called before the exception is raised.
using System;
using System.IdentityModel.Selectors;
namespace PsmDataProvider.Security
{
internal class CustomerUserNamePasswordValidator : UserNamePasswordValidator, ICustomerUserNamePasswordValidator
{
public CustomerUserNamePasswordValidator()
{
}
public override void Validate(string userName, string password)
{
if (userName == null) throw new ArgumentNullException("userName","The username must be provided in the request to access this service");
if (password == null) throw new ArgumentNullException("password", "The password must be provided in the request to access this service");
}
}
}
When I try to run the code in VS2012 through IIS Express the service fails to start with the below error.
If I remove the clientCredentialType from the configuration then it works but I require the additional security of using the username / password validation on the service and possibly at a method level in the future.
Is this something I have configured incorrectly in the WCF config or a problem with the configuration in IISExpress?
Please help...
The issue appears to be when using Basic Authentication when hosting the service in IIS as IIS wants to handle the authentication.
This is discussed in this MSDN blog post
In the version of WCF that shipped with .Net Framework 3.0 we didn't
support custom validators with transport level HTTP security. We
received much feedback from the community that this was a highly
desired feature, so I'm happy to say we added support for this
scenario in the 3.5 release of the .Net Framework. Note that this is
only supported under self hosted services.
There is a resolution as discussed in Allen Conway's Blog Post by implementing a custom authorisation manager derived from ServiceAuthorizationManager
CustomAuthorizationManager
public class CustomAuthorizationManager : ServiceAuthorizationManager
{
private const string UserName = "username";
private const string Password = "password";
protected override bool CheckAccessCore(OperationContext operationContext)
{
string authHeader = WebOperationContext.Current.IncomingRequest.Headers["Authorization"];
if ((authHeader != null) && (authHeader != string.Empty))
{
string[] svcCredentials = System.Text.ASCIIEncoding.ASCII
.GetString(Convert.FromBase64String(authHeader.Substring(6)))
.Split(':');
var user = new { Name = svcCredentials[0], Password = svcCredentials[1] };
if ((user.Name.Equals(UserName) && user.Password.Equals(Password)))
return true;
else
return false;
}
else
{
WebOperationContext.Current.OutgoingResponse.Headers.Add("WWW-Authenticate: Basic realm=\"PsmProvider\"");
throw new WebFaultException(HttpStatusCode.Unauthorized);
}
}
}
Config
<system.serviceModel>
<bindings>
<webHttpBinding>
<binding name="webInteropSecureBinding" allowCookies="false" maxBufferPoolSize="51200" maxBufferSize="51200" maxReceivedMessageSize="51200">
<security mode="Transport"/>
</binding>
</webHttpBinding>
</bindings>
<services>
<service name="PsmDataProvider.PsmProvider" behaviorConfiguration="SecureRest">
<clear />
<endpoint binding="webHttpBinding" bindingConfiguration="webInteropSecureBinding"
name="PsmProvider" contract="PsmDataProvider.IPsmProvider" behaviorConfiguration="webHttpBehavior" />
<endpoint address="mex" binding="mexHttpsBinding" name="mex" contract="IMetadataExchange" />
<host>
<baseAddresses>
<add baseAddress="https://localhost:44300/PsmProvider/" />
</baseAddresses>
</host>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="SecureRest">
<serviceMetadata httpGetEnabled="false" httpsGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true" />
<serviceAuthorization serviceAuthorizationManagerType="PsmDataProvider.Security.CustomAuthorizationManager, PsmDataProvider"/>
</behavior>
</serviceBehaviors>
<endpointBehaviors>
<behavior name="webHttpBehavior">
<webHttp/>
</behavior>
</endpointBehaviors>
</behaviors>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
</system.serviceModel>
Note
Also note a comment from Travich regarding the IIS / IIS Express configuration
Travich said... One thing to help other users. It was briefly stated,
but something I overlooked... Turn off Basic Auth in IIS and remove
tag from your webHttpBinding!
Works for me.
Setup is mono latest stable on raspberry pi, polling data from service on server with .NET 4.5.
My configuration for server side:
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior name="vlcBehaviour">
<serviceMetadata httpGetEnabled="true" />
</behavior>
</serviceBehaviors>
</behaviors>
<services>
<service name="ser.Serwys">
<endpoint address="net.tcp://192.168.56.1:9070/WindowService" binding="netTcpBinding" bindingConfiguration="AnonymousTcpBinding"
contract="Window.Service.IWindowServiceHost" />
</service>
</services>
<bindings>
<netTcpBinding>
<binding name="AnonymousTcpBinding" receiveTimeout="00:00:01"
sendTimeout="00:00:01"
maxBufferSize="1000"
maxConnections="100"
maxBufferPoolSize="100"
listenBacklog="200"
maxReceivedMessageSize="1000">
<security mode="None" />
</binding>
</netTcpBinding>
</bindings>
</system.serviceModel>
On client side:
<system.serviceModel>
<behaviors>
<endpointBehaviors>
<behavior name="maxItems">
<dataContractSerializer maxItemsInObjectGraph="2147483646" />
</behavior>
</endpointBehaviors>
</behaviors>
<bindings>
<netTcpBinding>
<binding name="AnonymousTcpBinding" openTimeout="00:00:01" receiveTimeout="00:00:01" sendTimeout="00:00:01" maxBufferSize="1000" maxConnections="200" listenBacklog="200" maxReceivedMessageSize="1000">
<security mode="None" />
</binding>
</netTcpBinding>
</bindings>
<client>
<endpoint name="WindowService" address="net.tcp://192.168.56.1:9070/WindowService" binding="netTcpBinding" bindingConfiguration="AnonymousTcpBinding" contract="Window.Service.IWindowServiceHost" />
</client>
</system.serviceModel>
Service contract:
namespace Window.Service
{
[ServiceContract(
Namespace = "http://window",
Name = "WindowHost")]
public interface IWindowServiceHost
{
[OperationContract]
void Connect(int windowId);
[OperationContract]
void Disconnect();
[OperationContract]
DisplayData GetData();
}
}
Implementation of service:
[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single, ConcurrencyMode = ConcurrencyMode.Single)]
public class Serwys:IWindowServiceHost
Method that is called:
public DisplayData GetData()
{
Console.WriteLine("Called get data {0}:{1}:{2}",DateTime.Now.Minute,DateTime.Now.Second,DateTime.Now.Millisecond);
return new DisplayData
{
BoxesInProgress = 1,
};
}
Call to GetData from client takes more and more time, don't know why.
I have tested it on Ubuntu also, Mono is latest version here how I log it:
Stopwatch stp = new Stopwatch();
stp.Start();
var data = remote.GetData();
stp.Stop();
log.WarnFormat("Polling service took: {0} ms", stp.ElapsedMilliseconds);
Any explanations?? I think it is Mono bug, because setup is really basic no concurrency method called is dead simple, and polling times are going up.
I call it on timer elapse, and for test I call it every 10ms but it is growing even if I call it every second, but slower, and this only gives me more time before all crashes.
When this JavaScript code is run, it tells me that "0x800a1391 - JavaScript runtime error: 'InputService' is undefined".
I have tried and tried, and I just can't seem to figure out of what I am missing...
Web.Config file (just the web service part):
<system.serviceModel>
<behaviors>
<endpointBehaviors>
<behavior name="CommonEndPointBehavior">
<enableWebScript/>
</behavior>
</endpointBehaviors>
</behaviors>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true"/>
<services>
<service name="InputService">
<endpoint name="" address="" behaviorConfiguration="CommonEndPointBehavior" binding="webHttpBinding" contract="InputService" bindingConfiguration="webBinding" />
</service>
</services>
<bindings>
<webHttpBinding>
<binding name="webBinding">
<!--<security mode="Transport">-->
<security mode="None"/>
</binding>
</webHttpBinding>
</bindings>
</system.serviceModel>
The Service:
[ServiceContract(Namespace = "")]
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
public class InputService
{
[OperationContract]
public string EditSiteElement(int siteid, string name, string url, string description, int siteorder, bool active)
{
return Input.EditSiteElement(siteid, name, url, description, siteorder, active);
}
}
The references in the web form:
scriptManagerProxy.Services.Add(new ServiceReference("~/User/Input.svc"));
scriptManagerProxy.Scripts.Add(new ScriptReference("~/User/Input.js"));
JavaScript file:
//When edit button is clicked on row.
function EditSiteElement(siteid) {
InputService.GetSiteIdInfo(siteid, function (result) {
var stuff = result.split('ยค');
$('[id$=TextBox_name]').val(stuff[0]);
$('[id$=TextBox_link]').val(stuff[1]);
$('[id$=TextBox_description]').val(stuff[2]);
$('[id$=CheckBox_active]').prop('checked', (stuff[3] == 'True'));
$('[id$=TextBox_order]').val(stuff[4]);
//Open the dialog
$("[id$=panel_Input]").dialog('open');
SiteIdForSave = siteid;
});
}
So, there are a couple of changes you have to do.
First, decorate the service method with the WebInvoke attribute which resides in the System.ServiceModel.Web namespace (you may have to add the reference to your project).
[OperationContract]
[System.ServiceModel.Web.WebInvoke] //add this attribute
public string EditSiteElement(int siteid, string name, string url, string description, int siteorder, bool active)
{
return Input.EditSiteElement(siteid, name, url, description, siteorder, active);
}
Second, in the InputService.svc file (in Visual Studio, right click on the InputService.svc file and select View Markup), add the Factory="System.ServiceModel.Activation.WebScriptServiceHostFactory" attribute:
<%# ServiceHost Language="C#" Debug="true" Factory="System.ServiceModel.Activation.WebScriptServiceHostFactory" Service="WebApplication6.InputService" CodeBehind="InputService.svc.cs" %>
Make sure that the target framework version for your application is 4.5.
[EDIT]
I suggest you modify the web.config's <system.serviceModel> section as follows. Please pay attention to the use of your namespaces (MyNamespace) and to the fact that I moved the behavior definition from the end point to the service level.
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior name="InputServiceBehavior">
<serviceMetadata httpGetEnabled="true"/>
<serviceDebug includeExceptionDetailInFaults="false"/>
</behavior>
</serviceBehaviors>
</behaviors>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true"/>
<services>
<service behaviorConfiguration="InputServiceBehavior" name="MyNamespace.InputService">
<endpoint address="" binding="webHttpBinding" contract="MyNamespace.InputService" bindingConfiguration="webBinding"/>
</service>
</services>
<bindings>
<webHttpBinding>
<binding name="webBinding">
<!--<security mode="Transport">-->
<security mode="None"/>
</binding>
</webHttpBinding>
</bindings>
</system.serviceModel>
I have created the simple web service.
Code:
[ServiceContract]
public interface ITsdxService
{
[OperationContract]
void DoWork();
[OperationContract]
string Test();
}
public class TsdxService : ITsdxService
{
public void DoWork()
{
}
public string Test()
{
return "Hello World!";
}
}
Web.config:
<system.serviceModel>
<services>
<service name="Test.TSDX.UI.TsdxService">
<endpoint
address="Tsdx"
binding="wsHttpBinding"
bindingConfiguration="TestBinding"
contract="Test.TSDX.UI.ITsdxService" />
</service>
</services>
<bindings>
<wsHttpBinding>
<binding name="TestBinding" />
</wsHttpBinding>
</bindings>
<behaviors>
<serviceBehaviors>
<behavior name="">
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="false" />
</behavior>
</serviceBehaviors>
</behaviors>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
</system.serviceModel>
When I run from Visual Studio I put localhost:50517/TsdxService.svc?wsdl all works fine - I can see wsdl, but when I put localhost:50517/TsdxService.svc/Tsdx/Test or localhost:50517/TsdxService.svc/Tsdx/DoWork I don't see anything. The Fiddler tells me that I got 400 error. Breakpoints (on Test and DoWork methods) don't work. Why? What did I do incorrect?
Add the WebGet attribute to your service operations.
[WebGet]
public string Test()
{
...
}
For this to work, you also need to add WebScriptEnablingBehavior to the service configuration. Also, use the webHttpBinding. These things are all required to allow the service to work as an AJAX service.
Definition:
<endpointBehaviors>
<behavior name="EndpointBehavior">
<enableWebScript />
</behavior>
</endpointBehaviors>
Reference:
<endpoint behaviorConfiguration="EndpointBehavior"
binding="webHttpBinding"
...
/>