I am developing a WCF and I want it to be called by both ways SOAP/REST.
Now I am able to get response by SOAP but unable to call the same WCF by JSON request.
IService1.cs
[OperationContract]
[FaultContract(typeof(CustomException))]
[WebInvoke(Method = "POST", UriTemplate = "/Validateuser",
RequestFormat = WebMessageFormat.Xml | WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Xml | WebMessageFormat.Json)]
ResponsetoCustomer Validateuser(ValidateCustomerInput validate);
Web.config
<system.serviceModel>
<services>
<service name="TractorMitraIntegration.IService1" behaviorConfiguration="ServBehave">
<!--Endpoint for SOAP-->
<endpoint
address="soapService"
binding="basicHttpBinding"
contract="TractorMitraIntegration.IService1"/>
<!--Endpoint for REST-->
<endpoint
address="XMLService"
binding="webHttpBinding"
behaviorConfiguration="restPoxBehavior"
contract="TractorMitraIntegration.IService1"/>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="ServBehave">
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true"/>
</behavior>
<behavior>
<!-- 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>
<endpointBehaviors>
<!--Behavior for the REST endpoint for Help enability-->
<behavior name="restPoxBehavior">
<webHttp helpEnabled="true"/>
</behavior>
</endpointBehaviors>
</behaviors>
<protocolMapping>
<add binding="basicHttpsBinding" scheme="https"/>
</protocolMapping>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true"/>
Below error I am facing,
Cannot process the message because the content type 'application/json' was not the expected type 'text/xml; charset=utf-8'
Please help!
You probably need defaultOutgoingResponseFormat="Json":
<behavior name="restPoxBehavior">
<webHttp helpEnabled="true" defaultOutgoingResponseFormat="Json" />
</behavior>
You cannot support both soap and rest for the same endpoint.
See this REST / SOAP endpoints for a WCF service for how to.
Related
I have added a RESTful WCF service inside a Web application(Righclicked solution and added WCF service) and while running it is exposing the url as svcutil.exe http://localhost:62783/Service1.svc?wsdl but i have tried calling that service UriTemplate from a RESTCLIENT like http://localhost:62783/AuthenticateUser it is throwing an error like
HTTP 404. The resource you are looking for (or one of its dependencies) could have been removed, had its name changed, or is temporarily unavailable. Please review the following URL and make sure that it is spelled correctly.
But if i create a seperate RESTful WCF service and calling from a RESTCLIENT is working fine.Here is my code
[OperationContract]
string AuthenticateUser1();
and
[WebInvoke(UriTemplate = "/AuthenticateUser", Method = "GET", BodyStyle = WebMessageBodyStyle.Bare, ResponseFormat = WebMessageFormat.Json)]
public string AuthenticateUser1()
{
return string.Format("Token {0}", new Guid().ToString());
}
and config
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior name="">
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="false" />
</behavior>
</serviceBehaviors>
</behaviors>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
</system.serviceModel>
Any suggestion??
Based on your posted config, you have a default endpoint for SOAP of basicHttpBinding, which is (by default) mapped to the http scheme. I've done very little with REST, but I believe you will need to add an endpoint using webHttpBinding to do REST, and most likely the URL will need to be http://localhost:62783/Service1.svc/AuthenticateUser (note the inclusion of the service file), though I'm not 100% sure on that one.
To add a REST endpoint, do something like this in your service's config file:
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior name="">
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="false" />
</behavior>
</serviceBehaviors>
<!-- Added for REST -->
<endpointBehaviors>
<behavior name="REST">
<webHttp />
</behavior>
</endpointBehaviors>
</behaviors>
<!-- REST endpoint -->
<endpoint address="" binding="webHttpBinding"
contract="<contract name with namespace>"
behaviorConfiguration="REST">
<serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
</system.serviceModel>
Again, REST is not my strong point, but this should hopefully get you pointed in the right direction at least.
I am trying to catalog for my own education the multiple ways services are used in an asp.net application.
When using a standard (i.e. non-ajax) WCF service, if you use an endpoint behavior with "webHttp", a json result is not wrapped with "d". If you use an endpoint behavior with "enableWebScript", you get the expected "d" wrapper.
Is this a feature of .net 4.5 now, or why is it that you don't get the "d" wrapper with webHttp?
My understanding now is that it is the underlying MS-AJAX infrastructure that implements the "d" wrapper, and if you use WCF without the AJAX infrastructure (e.g. if setting up a RESTful service), you avoid this.
I don't have any real complex implementation - I am just trying to capture the nuances of the different ways of implementing services - but just in case, here is the code I used to discover this behavior with "d".
Here is the exposed method:
[ServiceContract]
public interface IServicesDemo_WCF
{
[OperationContract]
[WebInvoke(Method = "GET", ResponseFormat = WebMessageFormat.Json)]
string ReturnWcfMessage();
}
Here is the config:
<system.serviceModel>
<behaviors>
<endpointBehaviors>
<behavior name="WebService.AJAX_WCFAspNetAjaxBehavior">
<enableWebScript />
</behavior>
<behavior name="WebService.WCFBehavior">
<webHttp />
</behavior>
</endpointBehaviors>
<serviceBehaviors>
<behavior name="">
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="false" />
</behavior>
<behavior name="WCFServiceBehavior">
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="false" />
</behavior>
</serviceBehaviors>
</behaviors>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true"
multipleSiteBindingsEnabled="true" />
<services>
<service name="WebService.ServicesDemo_AJAX_WCF">
<endpoint address="" behaviorConfiguration="WebService.AJAX_WCFAspNetAjaxBehavior"
binding="webHttpBinding" contract="WebService.ServicesDemo_AJAX_WCF" />
</service>
<service name="WebService.ServicesDemo_WCF" behaviorConfiguration="WCFServiceBehavior">
<endpoint address="" behaviorConfiguration="WebService.WCFBehavior"
binding="webHttpBinding" contract="WebService.IServicesDemo_WCF" />
</service>
</services>
Here is the call from client:
$.ajax({
type: "Get",
data: data,
contentType: "application/json; charset=utf-8",
url: "ServicesDemo_WCF.svc/ReturnWcfMessage",
success: function (data) {
$('#wcf_content').html(data);
},
error: function (msg) {
alert(msg);
}
});
I have an WCF and I'm needing to create this configuration dinamically because my
app.config never changes in client machines.
Any body help?
<behaviors>
<endpointBehaviors>
<!-- REST -->
<behavior name="restBehavior">
<webHttp defaultOutgoingResponseFormat="Json" defaultBodyStyle="Wrapped"/>
</behavior>
</endpointBehaviors>
<serviceBehaviors>
<behavior name="defaultBehavior">
<serviceDebug includeExceptionDetailInFaults="true" />
<serviceMetadata httpGetEnabled="true" />
</behavior>
</serviceBehaviors>
</behaviors>
<client>
<endpoint name="json" address="http://localhost:8080/json"
binding="webHttpBinding"
bindingConfiguration="webBinding"
behaviorConfiguration="restBehavior"
contract="ServiceReference.ServiceClientContract" />
</client>
Most WCF elements in the config file have a corresponding class or property that can be set in code (which is presumably what you meant by "dynamically"?) For example, 'endpointBehaviors' can be accessed through the Behaviors property of the ServiceEndpoint class:
Uri baseAddress = new Uri("http://localhost:8001/Simple");
ServiceHost serviceHost = new ServiceHost(typeof(CalculatorService), baseAddress);
ServiceEndpoint endpoint = serviceHost.AddServiceEndpoint(
typeof(ICalculator),
new WSHttpBinding(),
"CalculatorServiceObject");
endpoint.Behaviors.Add(new MyEndpointBehavior());
Console.WriteLine("List all behaviors:");
foreach (IEndpointBehavior behavior in endpoint.Behaviors)
{
Console.WriteLine("Behavior: {0}", behavior.ToString());
}
http://msdn.microsoft.com/en-us/library/system.servicemodel.description.serviceendpoint.behaviors.aspx
Searching any of the elements your are interested in configuring in MSDN should be enough to get you started.
This is my web.config file:
<bindings>
<basicHttpBinding>
<binding
name="ExtremeBinding"
maxBufferSize="12354000"
maxReceivedMessageSize="12354000" />
</basicHttpBinding>
</bindings>
<services>
<service name="WcfService3.Service1" behaviorConfiguration="myServiceBehaviour">
<endpoint
address=""
binding="basicHttpBinding"
bindingConfiguration="ExtremeBinding"
contract="WcfService3.IService1"
behaviorConfiguration="epBehavior"/>
</service>
</services>
<behaviors>
<endpointBehaviors>
<behavior name="epBehavior">
</behavior>
</endpointBehaviors>
<serviceBehaviors>
<behavior name="myServiceBehaviour">
<!-- 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>
</behaviors>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
If I keep it like this, and run the WCF Test Client, everything works fine.
But if I add anything to the endPoint Behavior, for example:
<behavior name="epBehavior">
<callbackDebug includeExceptionDetailInFaults="true"/>
</behavior>
the WCF Test Client fails with the Error:
Failed to add a service. Service metadata may not be accessible. Make sure your service is running and exposing metadata.
It seems as though it doesn't matter what I put within the . For example:
<behavior name="epBehavior">
<webHttp/>
</behavior>
It's clear to me that I missing something fundamental, but I can't figure what it is.
Thank you very much.
I don't know the exact reason why this happens, but I think you can fix this by adding a serviceMetadata behavior:
<behaviors>
<serviceBehaviors>
<behavior name="NewBehavior">
<serviceMetadata httpsGetEnabled="true"
httpsGetUrl="https://myComputerName/myEndpoint" />
</behavior>
</serviceBehaviors>
</behaviors>
This is from:
http://msdn.microsoft.com/en-us/library/ms731317.aspx
I am writing a WCF service, (json REST) and I have it working fine when using the wcftestclient.exe
When I run that test tool it triggers my break points while debugging and everything works as expected.
but, when using a browser to navigate to the the service and method, no break point is triggered. it seems as though the request isnt even getting to the code.
I receieve no errors on when navigating with web browser to the service, it just doesn't get any data, or trigger the break points.
Apologies if this is a duplicate, I have read and tried many many different configurations found in answers to similar questions, but nothing seems to work.
Many thanks for any help, I've posted my code below.
Martyn
I have setup:
ServiceContract
[OperationContract]
[WebGet(BodyStyle = WebMessageBodyStyle.Bare, ResponseFormat = WebMessageFormat.Json)]
List<Country> GetAllCountries();
The Service CLass:
public List<Country> GetAllCountries()
{
ControlServiceRepository rep = new ControlServiceRepository();
return rep.GetAllCountries().ToList() ;
}
and my web config
<system.web>
<compilation debug="true" targetFramework="4.0" />
</system.web>
<system.serviceModel>
<services>
<service name="OmniData" behaviorConfiguration="ServiceConfig">
<!-- Service Endpoints -->
<host>
<baseAddresses>
<add baseAddress="http://localhost:55641/"/>
</baseAddresses>
</host>
<endpoint address="" binding="webHttpBinding" contract="ControlService.IOmniData" behaviorConfiguration="rest" />
</service>
</services>
<behaviors>
<endpointBehaviors>
<behavior name="rest">
<webHttp helpEnabled="true"/>
</behavior>
</endpointBehaviors>
<serviceBehaviors>
<behavior name="ServiceConfig">
<serviceMetadata httpGetEnabled="true"/>
<serviceDebug includeExceptionDetailInFaults="false"/>
</behavior>
<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>
</behaviors>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
<standardEndpoints>
<webHttpEndpoint>
<standardEndpoint name="" helpEnabled="true" automaticFormatSelectionEnabled="false" defaultOutgoingResponseFormat="Json"/>
</webHttpEndpoint>
</standardEndpoints>
</system.serviceModel>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true"/>
</system.webServer>
I think there are some things missing in your contract
[OperationContract]
[WebInvoke(Method = "GET", UriTemplate = "/GetAllCountries", RequestFormat = WebMessageFormat.Json,ResponseFormat = WebMessageFormat.Json, BodyStyle = WebMessageBodyStyle.WrappedRequest)]
List<Country> GetAllCountries();
Try this.Let me know if it helps.
I got this working in the end by deleting all the end points in the config and using
RouteTable.Routes.Add(new ServiceRoute("", new WebServiceHostFactory(), typeof(OmniData)));
if anyone else has issues, this is even easier than setting up end points because you can just specify the type of responses and end points within the classes themselves.
so:
Add a global.asax if one does exist and include this:
protected void Application_Start(object sender, EventArgs e)
{
RouteTable.Routes.Add(new ServiceRoute("", new WebServiceHostFactory(), typeof(OmniData)));
}
decorate your Service class with
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
here is mine:
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
public class OmniData : IOmniData
{
public Country[] GetAllCountries()
{
ControlServiceRepository rep = new ControlServiceRepository();
return rep.GetAllCountries().ToArray() ;
}
}
then the interface you setup your endpoing and types using WebGet or WebInvoke
public interface IOmniData
{
[OperationContract]
[WebGet(UriTemplate = "OmniData/GetAllCountries", ResponseFormat = WebMessageFormat.Json, BodyStyle = WebMessageBodyStyle.Bare)]
Country[] GetAllCountries();
}
the UriTemplate is the end point, so to access the method you would use: http://MyService.com/OmniData/GetAllCountries
and finally, web config
<system.serviceModel>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true"/>
<standardEndpoints>
<webHttpEndpoint>
<standardEndpoint name="" helpEnabled="true" automaticFormatSelectionEnabled="false"/>
</webHttpEndpoint>
</standardEndpoints>
<services>
<service name="OmniData">
<!-- Service Endpoints -->
<host>
<baseAddresses>
<add baseAddress="http://localhost:55641"/>
</baseAddresses>
</host>
<endpoint address="" binding="webHttpBinding" contract="ControlService.IOmniData" behaviorConfiguration="rest" />
</service>
</services>
<behaviors>
<endpointBehaviors>
<behavior name="rest">
<webHttp />
</behavior>
</endpointBehaviors>
<serviceBehaviors>
<behavior name="Default">
<serviceMetadata httpGetEnabled="true"/>
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
Alot of help from here
but, importantly for what I wanted, json results, you need to make sure:
automaticFormatSelectionEnabled="false" is in there so it will use the response format specified in the interface. Otherwise you end up with XML instead.
hopefully this helps someone else
And thanks again for fiddler!
Martyn