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);
}
});
Related
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.
I created a WCF service, that is supposed to be consumed by Javascript(Json) on client side. Websites are generated by ASP.NET MVC. I got everything running on localhost IIS-Express.
Problem is, when I call this WCF service from Javascript, it throws and undefined error.
One of many thoughts, why this error occurs is, that WCF web.config is not set correctly and doesn't allow cross site scripting.
Here is web.config file
<?xml version="1.0"?>
<configuration>
<system.serviceModel>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
<services>
<service behaviorConfiguration="Default"
name="Wcf_Categories.Categories">
<endpoint address=""
behaviorConfiguration="webBehavior"
binding="webHttpBinding"
contract="Wcf_Categories.ICategories" />
<endpoint address="sc"
behaviorConfiguration="script"
binding="webHttpBinding"
bindingConfiguration="crossDomain"
contract="Wcf_Categories.ICategories"/>
<endpoint contract="IMetadataExchange" binding="mexHttpBinding"
address="mex" />
</service>
</services>
<bindings>
<webHttpBinding>
<binding name="crossDomain" crossDomainScriptAccessEnabled="true" />
</webHttpBinding>
</bindings>
<behaviors>
<endpointBehaviors>
<behavior name="webBehavior">
<webHttp helpEnabled="true" />
</behavior>
<behavior name="script">
<enableWebScript/>
</behavior>
</endpointBehaviors>
<serviceBehaviors>
<behavior name="Default">
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true" />
</behavior>
<behavior name="">
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true" />
</behavior>
</serviceBehaviors>
</behaviors>
</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>
<system.web>
<compilation debug="true"/>
</system.web>
</configuration>
If I call service directly from browser for example localhost:1813/Categories.svc/sc/GetData?name=undefined
it returns suggested data and behaves normally (sites running at localhost/TestSites/Products# )
Here is script for wcf service call
function GetCategories(categoryName) {
$.ajax({
type: "GET",
async: "false",
url: "localhost:1813/Categories.svc/sc/GetData",
contentType: "application/json; charset=utf-8",
dataType: "json",
data : 'name='+categoryName,
processData: true,
success: function (result) {
ServiceSucceeded(result);
},
error: ServiceFailed
});
}
function ServiceSucceeded(result) {
var resultObject;
if (DataType == "json") {
resultObject = result.GetUserResult;
for (i = 0; i < resultObject.length; i++) {
alert(resultObject[i]);
}
}
}
function ServiceFailed(xhr) {
alert(xhr.responseText);<---------------------- Alert output is "undefined". Exception details = [Exception... "<no message>" nsresult: "0x805e0006 (<unknown>)" location: "JS frame :: http://localhost/TestSites/content/js/jquery-1.10.2.min.js :: .send :: line 6" data: no] ------->
if (xhr.responseText) {
var err = xhr.responseText;
if (err)
error(err);
else
error({ Message: "Unknown server error." });
}
return;
}
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 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
I am trying to make a simple WCF RESTful for the first time to be consumed via JSON. I have my interface below, but what would be the URL I would call to invoke my MemberLogon() method?
I thought it would be this:
http://localhost:49701/Exchange.svc/?membershipNumber=6519548&blah=abc
but I get a 404. I have a feeling it is to do with my service configuraiton in my Web.Config. Help!
My interface and class is:
[ServiceContract]
public interface IExchange
{
[System.ServiceModel.OperationContract(Name = "MemberLogon")]
[WebInvoke(UriTemplate = "/?membershipNumber={membershipNumber}&blah={blah}", Method = "GET", ResponseFormat = WebMessageFormat.Json)]
Member MemberLogon(string membershipNumber, string blah);
}
[System.Runtime.Serialization.DataContract]
public class Member
{
[System.Runtime.Serialization.DataMember]
public string Username { get; set; }
}
Configuration is:
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior name="MyNamespace.MyClass.ExchangeBehavior">
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="false" />
</behavior>
</serviceBehaviors>
</behaviors>
<services>
<service behaviorConfiguration="MyNamespace.MyClass.ExchangeBehavior" name="MyNamespace.MyClass.Exchange">
<endpoint address="" binding="webHttpBinding" contract="MyNamespace.MyClass.IExchange" />
</service>
</services>
The code and interface look good. Can you try this configuration?
<system.serviceModel>
<behaviors>
<endpointBehaviors>
<behavior name="MyNamespace.MyClass.ExchangeBehavior">
<webHttp/>
</behavior>
</endpointBehaviors>
</behaviors>
<services>
<service name="MyNamespace.MyClass.Exchange">
<endpoint address="" binding="webHttpBinding" behaviorConfiguration="MyNamespace.MyClass.ExchangeBehavior" contract="MyNamespace.MyClass.IExchange" />
</service>
</services>
</system.serviceModel>