I am trying to POST some JSON data to a WCF Service Library.
I created a GettingStartedLib service interface:
namespace GettingStartedLib
{
[ServiceContract(Namespace = "http://Microsoft.ServiceModel.Samples")]
public interface IService
{
//[OperationContract]
[WebGet]
string EchoWithGet(string s);
//[OperationContract]
[WebInvoke(BodyStyle = WebMessageBodyStyle.WrappedRequest, RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json, UriTemplate = "EchoWithPost")]
string EchoWithPost(Person person);
}
}
And a service implementation class:
public class Service : IService
{
public string EchoWithGet(string s)
{
return "You said " + s;
}
public string EchoWithPost(Person p)
{
return "You said " + p.ToString();
}
}
And a Host
class Program
{
static void Main(string[] args)
{
String home = "http://localhost/services/";
WebServiceHost host = new WebServiceHost(typeof(Service), new Uri(home));
try
{
ServiceEndpoint ep = host.AddServiceEndpoint(typeof(IService), new WebHttpBinding(), "");
host.Open();
using (ChannelFactory<IService> cf = new ChannelFactory<IService>(new WebHttpBinding(), home))
{
cf.Endpoint.Behaviors.Add(new WebHttpBehavior());
IService channel = cf.CreateChannel();
// Get works fine
s = channel.EchoWithGet("Hello, world. GETGET");
// Discarded. Changing to HTTP
// s = channel.EchoWithPost({"FirstName": "Anthony"});
}
Console.WriteLine("Press <ENTER> to terminate");
Console.ReadLine();
host.Close();
}
catch (CommunicationException cex)
{
Console.WriteLine("An exception occurred: {0}", cex.Message);
host.Abort();
}
}
And a Person class:
namespace GettingStartedLib
{
[DataContract]
public class Person
{
[DataMember(Order = 0)]
public string FirstName { get; set; }
}
}
And a HTTP page client
$.post("localhost/services/EchoWithPost",
{
type: "POST",
url: "http://localhost/services/EchoWithPost",
contentType: "application/json; charset=utf-8",
processData: false,
dataType: "json",
data: { "FirstName": "Anthony" }
}, function (data) {
console.log(data);
});
And my network preview returns an error:
Endpoint Not found
The App.config for the services class
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<appSettings>
<add key="aspnet:UseTaskFriendlySynchronizationContext" value="true" />
</appSettings>
<system.web>
<compilation debug="true" />
</system.web>
<system.serviceModel>
<services>
<service name="GettingStartedLib.Service">
<host>
<baseAddresses>
<add baseAddress = "http://localhost/services/" />
</baseAddresses>
</host>
<endpoint address="" binding="basicHttpBinding" contract="GettingStartedLib.IService">
<identity>
<dns value="localhost"/>
</identity>
</endpoint>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior>
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
</configuration>
I search for TraceSVCViewer and added the code for it. There is a Process error log
The incoming message has an unexpected message format 'Raw'.
The expected message formats for the operation are 'Xml', 'Json'.
This can be because a WebContentTypeMapper has not been configured on the binding.
See the documentation of WebContentTypeMapper for more details.
Am I doing something wrong?
What about:
[OperationContract]
[WebInvoke(Method = "POST", BodyStyle = WebMessageBodyStyle.WrappedRequest, RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json, UriTemplate = "/EchoWithPost")]
string EchoWithPost(Person person);
<system.serviceModel>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
<services>
<service behaviorConfiguration="Default" name="GettingStartedLib.Service">
<host>
<baseAddresses>
<add baseAddress = "http://localhost/services/" />
</baseAddresses>
</host>
<endpoint address="" binding="webHttpBinding" contract="GettingStartedLib.IService">
<identity>
<dns value="localhost"/>
</identity>
</endpoint>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
</service>
</services>
<behaviors>
<endpointBehaviors>
<behavior name="webBehavior">
<webHttp helpEnabled="true" />
</behavior>
</endpointBehaviors>
<serviceBehaviors>
<behavior name="Default">
<serviceMetadata httpGetEnabled="true" />
</behavior>
<behavior name="">
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="false" />
</behavior>
</serviceBehaviors>
</behaviors>
Related
If a WCF service exposes three endpoints, then can we have different message inspectors for each endpoint? If yes then how can we apply on each endpoint?
First, you should create an endpoint behavior to apply a formatter you want.
class CustomInspectorEndpointBehavior : IEndpointBehavior
{
public void ApplyDispatchBehavior(ServiceEndpoint endpoint,
EndpointDispatcher endpointDispatcher)
{
endpointDispatcher.DispatchRuntime.MessageInspectors.Add(new CustomFormatter());
}
...
}
Or if there is a general logic, you can apply a behavior for each of the endpoints using a service behavior class:
class MultipleInspectorsServiceBehavior : IServiceBehavior
{
public void ApplyDispatchBehavior(ServiceDescription serviceDescription,
ServiceHostBase serviceHostBase)
{
foreach (var endpoint in serviceDescription.Endpoints)
endpoint.EndpointBehaviors.Add(new CustomInspectorEndpointBehavior());
}
...
}
Finally, you can apply endpoint behaviors from code...
var host = new ServiceHost(typeof(TheService));
foreach (var endpoint in host.Description.Endpoints)
endpoint.EndpointBehaviors.Add(new CustomInspectorEndpointBehavior(c));
(in case of service behavior)
var host = new ServiceHost(typeof(TheService));
host.Description.Behaviors.Add(new MultipleInspectorsServiceBehavior());
...Or from config:
<system.serviceModel>
<extensions>
<behaviorExtensions>
<add name="customInspectorEndpointBehavior"
type="CustomInspectorEndpointBehaviorExtensionElement, MyAssembly" />
</behaviorExtensions>
</extensions>
<behaviors>
<endpointBehaviors>
<behavior name="behavior1">
<customInspectorEndpointBehavior />
<!--maybe some other behaviors-->
</behavior>
<behavior name="behavior2">
<customInspectorEndpointBehavior />
<!--maybe some other behaviors-->
</behavior>
</endpointBehaviors>
</behaviors>
<services>
<service name="TheService">
<endpoint address="address1" ... contract="..." behaviorConfiguration="behavior1" />
<endpoint address="address2" ... contract="..." behaviorConfiguration="behavior1" />
<endpoint address="address3" ... contract="..." behaviorConfiguration="behavior2" />
</service>
</services>
</system.serviceModel>
For service behavior:
<system.serviceModel>
<extensions>
<behaviorExtensions>
<add name="multipleInspectorsServiceBehavior"
type="MultipleInspectorsServiceBehaviorExtensionElement, MyAssembly" />
</behaviorExtensions>
</extensions>
<behaviors>
<serviceBehaviors>
<behavior name="CustomServiceBehavior">
<multipleInspectorsServiceBehavior />
<!--maybe some others-->
</behavior>
</serviceBehaviors>
</behaviors>
<services>
<service name="TheService" behaviorConfiguration="ServiceBehavior">
<endpoint address="address1" ... contract="..." />
<endpoint address="address2" ... contract="..." />
<endpoint address="address3" ... contract="..." />
</service>
</services>
</system.serviceModel>
Here you should create a BehaviorExtensionElement to reference behaviors in the config:
class CustomInspectorEndpointBehaviorExtensionElement : BehaviorExtensionElement
{
public override Type BehaviorType
{
get
{
return typeof(CustomInspectorEndpointBehavior);
}
}
protected override object CreateBehavior()
{
return new CustomInspectorEndpointBehavior();
}
}
class MultipleInspectorsServiceBehaviorExtensionElement : BehaviorExtensionElement
{
public override Type BehaviorType
{
get
{
return typeof(MultipleInspectorsServiceBehavior);
}
}
protected override object CreateBehavior()
{
return new MultipleInspectorsServiceBehavior();
}
}
I have a very simple WCF service that is hosted within a windows application. I'm tring to access the service by using GET method but just getting an empty page. I guess there is something wrong with configuration but I could't figure out what. Here is the codes:
WCFService.cs
namespace WCFServiceApp
{
[ServiceContract]
public class WCFService
{
[OperationContract]
[WebGet]
public int GetNumbers()
{
return 12345;
}
}
}
Form1.cs
private static Uri baseAddress = new Uri("http://localhost:8090");
private ServiceHost host = new ServiceHost(typeof(WCFService), baseAddress);
protected override void OnLoad(EventArgs e)
{
ServiceMetadataBehavior smb = new ServiceMetadataBehavior();
smb.HttpGetEnabled = true;
smb.MetadataExporter.PolicyVersion = PolicyVersion.Policy15;
host.Description.Behaviors.Add(smb);
host.Open();
base.OnLoad(e);
}
App.config
<?xml version="1.0"?>
<configuration>
<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/></startup>
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior name="WCFServiceBehavior">
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="false" />
</behavior>
</serviceBehaviors>
<endpointBehaviors>
<behavior name="WebBehavior">
<webHttp />
</behavior>
</endpointBehaviors>
</behaviors>
<services>
<service name="WCFService" behaviorConfiguration="WCFServiceBehavior">
<endpoint address="ws" binding="wsHttpBinding" contract="WCFService">
</endpoint>
<endpoint address="" behaviorConfiguration="WebBehavior" binding="webHttpBinding" contract="WCFService">
</endpoint>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
</service>
</services>
</system.serviceModel>
</configuration>
When I hit localhost:8090 with browser I see WCF welcome page. When I hit localhost:8090/GetNumbers just getting an empty page instead of the numbers.
I am building simple WCF web service for my mobile web app.
I am stack at the point of making the $.ajax request to WCF which comes back with 405 - Method not allow, even though when I do http://http://localhost:35798/RestServiceImpl.svc/json/23 I can see result of the ReturnJSONData() in the browser.
I went through 100's of different post, but none of the answer fixed my problem.
AJAX Request
$.ajax({
type: "GET",
url: "http://localhost:35798/RestServiceImpl.svc/json/34",
contentType: "application/json; charset=utf-8",
success: function(data) {
console.log(data);
},
});
IRestServiceImpl.cs
namespace RestService{
[ServiceContract]
public interface IRestServiceImpl
{
[OperationContract]
[WebInvoke(
Method = "GET",
ResponseFormat = WebMessageFormat.Json,
BodyStyle = WebMessageBodyStyle.Wrapped,
UriTemplate = "json/{id}"
)]
string ReturnJSONData(string id);
}
}
RestServiceImpl.svs.cs
namespace RestService {
public class RestServiceImpl : IRestServiceImpl {
public string ReturnJSONData(string id) {
return "You requested product " + id;
}
}
}
WebConfig
<?xml version="1.0"?>
<configuration>
<system.web>
<compilation debug="true" targetFramework="4.0" />
</system.web>
<system.serviceModel>
<services>
<service name="RestService.RestServiceImpl" behaviorConfiguration="ServiceBehaviour">
<endpoint address ="" binding="webHttpBinding" contract="RestService.IRestServiceImpl" behaviorConfiguration="web">
</endpoint>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="ServiceBehaviour">
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true" />
</behavior>
</serviceBehaviors>
<endpointBehaviors>
<behavior name="web">
<webHttp/>
</behavior>
</endpointBehaviors>
</behaviors>
<standardEndpoints>
<webHttpEndpoint>
<standardEndpoint name=""
helpEnabled="true"
automaticFormatSelectionEnabled="true"
defaultOutgoingResponseFormat ="Json"
crossDomainScriptAccessEnabled="true"/>
</webHttpEndpoint>
</standardEndpoints>
</system.serviceModel>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true"/>
</system.webServer>
</configuration>
Any suggestion much appreciated.
I have a WCF service with Net.Tcp binding, my server configuration is
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior name="">
<serviceMetadata httpGetEnabled="true" />
<serviceDebug httpHelpPageEnabled="true" includeExceptionDetailInFaults="true"/>
<serviceCredentials>
<userNameAuthentication userNamePasswordValidationMode="Custom"
customUserNamePasswordValidatorType="Service.PlainUserNameValidator, Service" />
</serviceCredentials>
</behavior>
</serviceBehaviors>
</behaviors>
<services>
<service name="Service.TestService">
<endpoint address="" binding="netTcpBinding" contract="Service.ITestService">
<identity>
<dns value="localhost" />
</identity>
</endpoint>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
<host>
<baseAddresses>
<add baseAddress="net.tcp://localhost:8732/Service/TestService/" />
<add baseAddress="http://localhost:8001/service/TestServiceMex/" />
</baseAddresses>
</host>
</service>
</services>
</system.serviceModel>
</configuration>
In the configuration I turned on customUserNamePasswordValidatorType. The code to start the host is
class Program
{
static void Main(string[] args)
{
using (ServiceHost host = new ServiceHost(typeof(TestService)))
{
host.Open();
Console.WriteLine("The service is ready.");
Console.WriteLine(String.Format("Metadata is at {0}?WSDL", host.Description.Endpoints[0].Address));
Console.WriteLine();
Console.WriteLine("Press <ENTER> to terminate service.");
Console.WriteLine();
Console.ReadLine();
}
}
}
And my custom username validator class registered in config file is
namespace Service
{
using System;
using System.IdentityModel.Selectors;
public class PlainUserNameValidator : UserNamePasswordValidator
{
public override void Validate(string userName, string password)
{
Console.WriteLine("Requesting username {0} and password {1}.", userName, password);
}
}
}
However the validator never seems to fire while the client is calling.
Any special trick I need to notice to enable customUserNamePasswordValidatorType for Net.Tcp binding?
Two points:
You havent included a certificate, you should do so to ensure the integrity of the client's credentials, set up a temporary one if you have to and add this to your service credentials.
<serviceCertificate
findValue="localhost"
x509FindType="FindBySubjectName"
storeLocation="CurrentUser"
storeName="My" />
You also havent specified any security - for this to work, both client and service endpoints need to enable Username and Password authentication mode on their bindings
<netTcpBinding>
<binding name="tcpWithMessageSecurity">
<security mode="Message" >
<message clientCredentialType="UserName"/>
</security>
</binding>
</netTcpBinding>
then
<endpoint address="" binding="tcpWithMessageSecurity" contract="Service.ITestService">
Then, name your behavior and add it in the above line.
I am pretty new to wcf and am trying to get a wcf extension to register and so I can ultimatly open/close an NHibernate session.
However I followed the details at Adam Matusiaks blog. I had to make a few guesses as it didnt compile first time. (NHibernateEndpointExtension : IExtension this iheritance had no type inthe example).
It just wont register the extension. When I make the wcf call it has no extensions in the collection.
There are no error messages and nothing is appearing in any logs I can see
DOES ANYONE KNOW WHERE I CAN LOOK AT SOME LOGGING Or anything
My web.config is as follows
<system.serviceModel>
<extensions>
<behaviorExtensions>
<add name="NHibernateExtension" type="SMS.Infrastructure.NHibernateEndpointExtension, SMS.Infrastructure, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
</behaviorExtensions>
</extensions>
<bindings>
<basicHttpBinding>
<binding name="AmjBasicHttpEndpointBinding">
<security mode="TransportCredentialOnly">
<transport clientCredentialType="Windows" />
</security>
</binding>
</basicHttpBinding>
<wsHttpBinding>
<binding name="AmjWsBinding">
<security>
<transport proxyCredentialType="Windows" />
</security>
</binding>
</wsHttpBinding>
</bindings>
<behaviors>
<serviceBehaviors>
<behavior name="SMS.Services.BEIMBehavior">
<serviceMetadata httpGetEnabled="true" />
<!-- set thsi to false if you dont want helpfult stack traces-->
<serviceDebug includeExceptionDetailInFaults="true" />
</behavior>
</serviceBehaviors>
</behaviors>
<services>
<service behaviorConfiguration="SMS.Services.BEIMBehavior" name="SMS.Services.BEIM">
<endpoint address="" binding="wsHttpBinding" bindingConfiguration="AmjWsBinding"
name="BeimServices" contract="SMS.Services.IBEIM">
<identity>
<dns value="localhost" />
</identity>
</endpoint>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
</service>
</services>
</system.serviceModel>
The classes that I am using are a s follows, I've got rid of the nhibernate stuff for now as I can deal with that when the extension is registered
namespace SMS.Infrastructure
{
public class NHibernateEndpointExtension : IExtension<OperationContext>
{
public NHibernateEndpointExtension()
{
}
public NHibernate.ISession NHibernateSession{ get; set; }
public void Attach(OperationContext owner)
{
}
public void Detach(OperationContext owner)
{
}
}
public class NHibernateEndpointContextInitializer : ICallContextInitializer
{
public object BeforeInvoke(InstanceContext instanceContext, IClientChannel channel, Message message)
{
bool found = false;
foreach (IExtension<OperationContext> extension in OperationContext.Current.Extensions)
{
if (extension is NHibernateEndpointExtension)
{
found = true;
break;
}
}
if (!found)
{
OperationContext.Current.Extensions.Add(new NHibernateEndpointExtension());
}
return NHibernateWcfSessionProvider.Instance.OpenSession();
}
public void AfterInvoke(object correlationState)
{
NHibernateWcfSessionProvider.Instance.CloseSession(((NHibernate.ISession)correlationState));
((IDisposable)correlationState).Dispose();
}
}
public class NHibernateEndpointBehavior : BehaviorExtensionElement, IEndpointBehavior
{
public override Type BehaviorType
{
get { return typeof(NHibernateEndpointBehavior); }
}
protected override object CreateBehavior()
{
return new NHibernateEndpointBehavior();
}
public void Validate(ServiceEndpoint endpoint)
{
}
public void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters)
{
}
public void ApplyDispatchBehavior(ServiceEndpoint endpoint,
EndpointDispatcher endpointDispatcher)
{
foreach (DispatchOperation operation in endpointDispatcher.DispatchRuntime.Operations)
{
operation.CallContextInitializers.Add(new NHibernateEndpointContextInitializer());
}
}
public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime)
{
}
}
public class NHibernateWcfSessionProvider
{
public NHibernateWcfSessionProvider()
{
}
private static NHibernateWcfSessionProvider instance;
public static NHibernateWcfSessionProvider Instance
{
get
{
if (instance == null)
{
instance = new NHibernateWcfSessionProvider();
}
return instance;
}
}
private ISessionFactory sessionFactory;
public void CreateSessionFactory()
{
sessionFactory= NHibernateHelper.CreateSessionFactory();
}
public NHibernate.ISession GetSession()
{
// get Nhibernate session from OperationContext or HttpContext
return ISession // just here to show that a session will be returned
}
public NHibernate.ISession OpenSession()
{
// get Nhibernate session from OperationContext or HttpContext
return ISession // just here to show that a session will be returned
}
public void CloseSession()
{
CloseSession(null);
}
public void CloseSession(NHibernate.ISession session)
{
///Closes NHibernate session cleanly
}
}
I haven't really tried to execute this, so there might be more issues than shown below, please bear with me.
It looks like you only registered the behavior extension (using the system.serviceModel\extensions\behaviorExtensions\add element). You also need to add it to a binding configuration by adding the respective element (by the name you specified when registering). In your case that should be:
<behaviors>
<serviceBehaviors>
...
</serviceBehaviors>
<endpointBehaviors>
<behavior name="MyEpBehavior">
<!-- ... possibly other stuff ... -->
<NHibernateExtension/>
</behavior>
</endpointBehaviors>
</behaviors>
<services>
<service behaviorConfiguration="SMS.Services.BEIMBehavior" name="SMS.Services.BEIM">
<endpoint address="" binding="wsHttpBinding" bindingConfiguration="AmjWsBinding"
name="BeimServices" contract="SMS.Services.IBEIM"
configuration="MyEpBehavior"> <!-- SET ENDPOINT BEHAVIOR -->
<identity>
<dns value="localhost" />
</identity>
</endpoint>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
</service>
</services>
From your question it is not certain whether you tried, but when troubleshooting the WCF mechanics, it is usually quite helpful to enable WCF tracing - although I'm not sure if it would have to say anything about this particular issue.
Got it working, I had the behaviour Extension pointing at the wrong class was NHibernateEndpointExtension but should have been
NHibernateEndpointBehavior. And then it all slotted in. I would recommend that anyone else use the WCF service configuration manager (VS2010 Tools menu)
The final web.config looks like this
<system.serviceModel>
<extensions>
<behaviorExtensions>
<add name="NHibernateExtension" type="SMS.Infrastructure.NHibernateEndpointBehavior, SMS.Infrastructure, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null" />
</behaviorExtensions>
</extensions>
<bindings>
<basicHttpBinding>
<binding name="AmjBasicHttpEndpointBinding">
<security mode="TransportCredentialOnly">
<transport clientCredentialType="Windows" />
</security>
</binding>
</basicHttpBinding>
<wsHttpBinding>
<binding name="AmjWsBinding">
<security>
<transport proxyCredentialType="Windows" />
</security>
</binding>
</wsHttpBinding>
</bindings>
<behaviors>
<endpointBehaviors>
<behavior name="NHibernateBehavior">
<NHibernateExtension />
</behavior>
</endpointBehaviors>
<serviceBehaviors>
<behavior name="SMS.Services.BEIMBehavior">
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true" />
</behavior>
</serviceBehaviors>
</behaviors>
<services>
<service behaviorConfiguration="SMS.Services.BEIMBehavior" name="SMS.Services.BEIM">
<endpoint address="" behaviorConfiguration="NHibernateBehavior"
binding="wsHttpBinding" bindingConfiguration="AmjWsBinding"
name="BeimServices" contract="SMS.Services.IBEIM">
<identity>
<dns value="localhost" />
</identity>
</endpoint>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
</service>
</services>
</system.serviceModel>