Can I use JSON in a WCF Service that uses wsHttpBinding? - asp.net

I need to use wsHttpBinding binding because my service needs access to HttpContext.Current.Session. I understand from my research that this is not possible with webHttpBinding. However all of my ajax is written to use JSON and I would like it very much if I didn't have to rewrite all of it.
My service works perfectly with webHttpBinding until I need to use the session.
Or, is there a way to get webHttpBinding access to the session?
EDIT:
<system.serviceModel>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" />
<behaviors>
<endpointBehaviors>
<behavior name="LiteBehavior">
<webHttp/>
</behavior>
</endpointBehaviors>
<serviceBehaviors>
<behavior name="LiteBehavior">
<serviceMetadata httpGetEnabled="true"/>
<serviceDebug includeExceptionDetailInFaults="true"/>
</behavior>
</serviceBehaviors>
</behaviors>
<services>
<service behaviorConfiguration="LiteBehavior" name="Lite.CMS.Services.LiteService">
<endpoint behaviorConfiguration="LiteBehavior" address="" binding="webHttpBinding" contract="Lite.CMS.Services.Interfaces.ILiteService" />
</service>
</services>
</system.serviceModel>
And my contract:
[ServiceContract (SessionMode=SessionMode.Allowed)]
public interface ILiteService
{
[WebInvoke(Method = "POST", ResponseFormat = WebMessageFormat.Json, RequestFormat = WebMessageFormat.Json, BodyStyle = WebMessageBodyStyle.WrappedRequest)]
[OperationContract]
void Item_Save(string Name);
}
And Implementation:
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Required)]
public class LiteService : ILiteService
{
public void Item_Save(string Name)
{
// I can't get access to HttpContext.Current.Session variables here.
}
}

webHttpbinding is a stateless binding, it doesn't use SOAP.
If you try to put SessionMode=SessionMode.Required it will throw an error on service start.
If you want to implement session on a stateless protocol, you'll need to do it by hand with cookies.
See :
http://social.msdn.microsoft.com/Forums/en-US/wcf/thread/fe2a2ce9-ba97-4784-95f8-bdce5ffcd8eb/
How to Manage Sessions in Restful WCF Service
REST WCF service and Session‏ in ASP.NET

Related

hosintg WCF rest services in .net webforms app

I have a traditional .net web application with .aspx pages and code behind files...
I want to use some jquery on the UI and wanted to ass json services to connect things like grids from jquery-easyui. I have seen some bad options like using .aspx pages to return json content type and standalone wcf samples but I want to host the services in IIS because the application is on a hosted online provider.
what is the simplest method that would be good practice to use for this and how do I implement it in VS2012 and my local IIS hosted site plus th production internet site?
You can use Web.Api to create rest services and host them as part of your website.
Have a look here for a complete tutorial : http://www.asp.net/web-api/tutorials/hands-on-labs/build-restful-apis-with-aspnet-web-api.
You can also include WCF services directly into your web application and configure them so they will return and receive JSON.
They look like this :
[ServiceContract(Namespace = "")]
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
public class YourServiceDoesJSON
{
[OperationContract]
[WebGet(ResponseFormat = WebMessageFormat.Json)]
public ReturnTypeThatWillBeTransformedIntoJSON GetWhatever(string parameterIfYouNeed)
{
// do something
return new ReturnTypeThatWillBeTransformedIntoJSON();
}
[OperationContract]
[WebInvoke(Method = "POST", RequestFormat = WebMessageFormat.Json, BodyStyle = WebMessageBodyStyle.WrappedRequest, ResponseFormat = WebMessageFormat.Json)]
public SomethingElse PostWhatever()
{
...
}
}
The config file for this service looks like this :
<system.serviceModel>
<behaviors>
<endpointBehaviors>
<behavior name="WebApp.Folder.YourServiceDoesJSONAspNetAjaxBehavior">
<webHttp/>
</behavior>
</endpointBehaviors>
<serviceBehaviors>
<behavior name="MetadataBehaviors" >
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true"/>
</behavior>
</serviceBehaviors>
</behaviors>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" />
<services>
<service name="WebApp.Folder.YourServiceDoesJSON" behaviorConfiguration="MetadataBehaviors">
<endpoint address="" behaviorConfiguration="WebApp.Folder.YourServiceDoesJSONAspNetAjaxBehavior"
binding="webHttpBinding" contract="WebApp.Folder.YourServiceDoesJSON" />
</service>
</services>
Note: this is how I did before I knew it was so easy to turn a web application into MVC; see my previous answer ;)

WCF service using ASP.Net Forms authentification - error during $.ajax() call when cookie is expired

I have a WCF service hosted in IIS web site with forms authentification. The service has [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Required)]
attribute and web config has this line:<serviceHostingEnvironment aspNetCompatibilityEnabled="true" />
Service is called form page with $.ajax() call. Everithing works fine until when user calls service after his cookie has expired.
In this situation the window "Windows Security" appears, saing that user should put in login and password to access the service.
If the user just closes the windows without doing anything, the page is redirected to Login Page (that is right)
The question: how to skip this window and make redirection immidiately?
I guess there is something with configuring WCF service and I tried some schemes of binding - yet I can't escape this window.
The configuration of WCF service:
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior name="metadataAndDebug">
<serviceMetadata httpGetEnabled="true" httpGetUrl=""/>
<serviceDebug includeExceptionDetailInFaults="true" />
</behavior>
</serviceBehaviors>
<endpointBehaviors>
<behavior name="Project.Service.DataServiceAspNetAjaxBehavior">
<enableWebScript/>
</behavior>
</endpointBehaviors>
</behaviors>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
<services>
<service name="Project.Service.DataService" behaviorConfiguration="metadataAndDebug" >
<endpoint address="" behaviorConfiguration="Project.Service.DataServiceAspNetAjaxBehavior"
binding="webHttpBinding" contract="Project.Service.DataService" />
</service>
</services>
the feature autoredirect is on by default.
If for some reason, you want to turn this feature off, you can register a message inspector to do that.
public class MyMessageInspector : IDispatchMessageInspector
{
internal const string RedirectPropertyName = "WebHttpRedirect";
public object AfterReceiveRequest(ref System.ServiceModel.Channels.Message request, IClientChannel channel, InstanceContext instanceContext)
{
// remove the RedirectPropertyName from the request
if ( request.Properties.ContainsKey(RedirectPropertyName))
{
request.Properties.Remove(RedirectPropertyName);
}
return null;
}
public void BeforeSendReply(ref System.ServiceModel.Channels.Message reply, object correlationState)
{
}
}

WCF web service error: The service cannot be activated because it does not support ASP.NET compatibility

I am trying to create a restful wcf web service. When I try to connect to the service through the client I get the following error:
The service cannot be activated because it does not support ASP.NET compatibility. ASP.NET compatibility is enabled for this application. Turn off ASP.NET compatibility mode in the web.config or add the AspNetCompatibilityRequirements attribute to the service type with RequirementsMode setting as 'Allowed' or 'Required'.
Others have had problems, but they fixed it through changes to their web.config. I have implemented their fix, but still the problem exists. here is my web.config:
<system.serviceModel>
<behaviors>
<endpointBehaviors>
<behavior name="WebBehavior" >
<webHttp />
</behavior>
</endpointBehaviors>
<serviceBehaviors>
<behavior name="MyServiceBehavior">
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true" />
</behavior>
<behavior name="">
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="false" />
</behavior>
</serviceBehaviors>
</behaviors>
<services>
<service behaviorConfiguration="MyServiceBehavior" name="myfirstwcf">
<endpoint address="ws" binding="basicHttpBinding"
contract="Imyfirstwcf" />
<endpoint address="ws2" binding="wsHttpBinding"
contract="Imyfirstwcf" />
<endpoint address="" behaviorConfiguration="WebBehavior"
binding="webHttpBinding"
contract="Imyfirstwcf" />
<endpoint address="mex" binding="mexHttpBinding"
contract="IMetadataExchange" />
</service>
</services>
<serviceHostingEnvironment aspNetCompatibilityEnabled= "true"
multipleSiteBindingsEnabled="true" />
</system.serviceModel>
On your main service you could mark your service as:
[AspNetCompatibilityRequirements(
RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
From http://forums.silverlight.net/t/21944.aspx
it will work :
you have change this lines in code or add the line in web.config:
<system.serviceModel>
<serviceHostingEnvironment aspNetCompatibilityEnabled="false" multipleSiteBindingsEnabled="true" />
</system.serviceModel>
If someone has a lot of services and services are created using custom ServiceHostFactory, then AspNetCompatibilityRequirementsAttribute can also be set in CreateServiceHost method.
Example:
public class HostFactory : ServiceHostFactory
{
protected override ServiceHost CreateServiceHost(Type serviceType, Uri[] baseAddresses)
{
var host = new ServiceHost(serviceType, baseAddresses);
//other relevent code to configure host's end point etc
if (host.Description.Behaviors.Contains(typeof(AspNetCompatibilityRequirementsAttribute)))
{
var compatibilityRequirementsAttribute = host.Description.Behaviors[typeof(AspNetCompatibilityRequirementsAttribute)] as AspNetCompatibilityRequirementsAttribute;
compatibilityRequirementsAttribute.RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed;
}
else
{
host.Description.Behaviors.Add(new AspNetCompatibilityRequirementsAttribute() { RequirementsMode =AspNetCompatibilityRequirementsMode.Allowed});
}
return host;
}
}
Actually, as per the latest documentation you need to do 2 things,
1.For your service class:
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
[ServiceBehavior(Namespace = "url")]
public class Service : IService
{
}
2.For web.config
<system.serviceModel>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true"/>

JSON WCF Service 404 on deployment server

I'm trying to deploy a WCF Service to my server, it works just the way I want it to locally. But on the server I get a 404 message.
This is what it looks like when I call my test method locally:
Image of the wanted result
When I deploy it I can still successfully browse to:
www.my domain name.com/Service1.svc
but when I go to:
www.my domain name.com/Service1.svc/test
I get a 404 error. What could be causing this?
This is all relevant code:
IService1.cs
namespace HighscoreWebService
{
[ServiceContract]
public interface IService1
{
[OperationContract]
[WebGet(UriTemplate = "Test",
ResponseFormat = WebMessageFormat.Json,
BodyStyle = WebMessageBodyStyle.Bare)]
string Test();
}
}
Service1.svc.cs
namespace HighscoreWebService
{
public class Service1 : IService1
{
public string Test()
{
return "Hello world!";
}
}
}
Part of Web.config
<system.serviceModel>
<services>
<service name="HighscoreWebService.Service1"
behaviorConfiguration="jsonRestDefault">
<host>
<baseAddresses>
<add baseAddress="http:/xxxxxx"/>
</baseAddresses>
</host>
<endpoint name="jsonRestEndpoint"
behaviorConfiguration="RESTFriendly"
binding="webHttpBinding"
contract="HighscoreWebService.IService1">
</endpoint>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="jsonRestDefault">
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true"/>
</behavior>
</serviceBehaviors>
<endpointBehaviors>
<behavior name="RESTFriendly">
<webHttp/>
</behavior>
</endpointBehaviors>
</behaviors>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
I suspect I made something wrong in the web.config. I'm very new to asp.net so it's possible I made any number of beginner mistakes. But because this works locally it could be something wrong with the configuration of the server I guess. Or something in the web.config I need to do to adapt to the server configuration.
Thank you for reading this.
try adding an "address" tag in your web.config endpoint. Here is an example of what I have in my WCF testing project. Though I would think that it should work how you have it. This may sound silly too, but make sure the request you are making to the service is actually an HTTP GET. Maybe post your client code too, if any of that doesnt work.
<endpoint binding="webHttpBinding" bindingConfiguration="testBinding" contract="ASMXtoWCF.IWcf"
address="test" behaviorConfiguration="RestServiceBehavior">
</endpoint>
You have to add to your merhodTest the behaviorto accept GET request (by default it accepts only POST). To do this add the WebInvoke behavior to it, for example by adding the following attribute to your method implementation (it's a behavior)
[WebInvoke(Method = "GET", ResponseFormat = WebMessageFormat.Json)]
btw you can remove the host tag from your web config it is unecessary

Hide REST methods from SOAP WCF Client

I created a simple WCF Service interface:
namespace ApiDoc.SampleApi
{
/// <summary>
/// Contract
/// </summary>
/// <webMethodsPrefix>Web</webMethodsPrefix>
[ServiceContract(Namespace = "apidoc.sampleapi.com", Name = "SampleApi")]
public interface IService
{
[WebGet( UriTemplate = "Add?value1={value1}&value2={value2}&apiKey={apiKey}", BodyStyle = WebMessageBodyStyle.Bare)]
AddRs AddWithHttpGet(int value1, int value2, string apiKey);
[WebInvoke(Method = "POST", UriTemplate = "Add", BodyStyle = WebMessageBodyStyle.Bare)]
AddRs Add(AddRq rq);
}
}
In this case it is just a simple Add operation.
It works well for Xml, Soap and Json. Both Get and Post.
The issue I am having is in Soap when I create a Service Reference to this service. I can call both functions "Add" and "AddWithHttpGet", while I only would like to see "Add".
I originally thought it was related to using "OperationContract" attribute, but it seems like it is not used any longer. I tried adding this attribute only to POST Add, but it doesn't make any difference. I am using ASP.NET 4.0.
Another solution would be to create a different IService for Soap, but I would rather keep this all in one interface.
Here is my config file:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<system.web>
<compilation debug="true" targetFramework="4.0" />
</system.web>
<system.serviceModel>
<bindings>
<webHttpBinding>
<binding name="jsonHttpBinding" />
<binding name="xmlHttpBinding" />
</webHttpBinding>
</bindings>
<services>
<service name="ApiDoc.SampleApi.Service" behaviorConfiguration="ApiDocSampleApiBehavior">
<host>
<baseAddresses>
<add baseAddress="http://localhost/ApiDoc.SampleApi/" />
</baseAddresses>
</host>
<endpoint name="soap" address="" binding="basicHttpBinding" bindingNamespace="apidoc.sampleapi.com" contract="ApiDoc.SampleApi.IService" lockAttributes="bindingNamespace" />
<endpoint name="json" address="json" binding="webHttpBinding" bindingNamespace="apidoc.sampleapi.com" bindingConfiguration="jsonHttpBinding" contract="ApiDoc.SampleApi.IService" behaviorConfiguration="JsonBehavior" />
<endpoint name="xml" address="xml" binding="webHttpBinding" bindingNamespace="apidoc.sampleapi.com" bindingConfiguration="xmlHttpBinding" contract="ApiDoc.SampleApi.IService" behaviorConfiguration="XmlBehavior" />
<endpoint name="mex" address="mex" binding="mexHttpBinding" bindingNamespace="apidoc.sampleapi.com" contract="IMetadataExchange" />
</service>
</services>
<behaviors>
<endpointBehaviors>
<behavior name="JsonBehavior">
<webHttp defaultOutgoingResponseFormat="Json" />
</behavior>
<behavior name="XmlBehavior">
<webHttp defaultOutgoingResponseFormat="Xml" />
</behavior>
</endpointBehaviors>
<serviceBehaviors>
<behavior name="ApiDocSampleApiBehavior">
<serviceMetadata httpGetEnabled="true" httpGetUrl="" />
<serviceDebug includeExceptionDetailInFaults="true" />
</behavior>
</serviceBehaviors>
</behaviors>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true" aspNetCompatibilityEnabled="true" minFreeMemoryPercentageToActivateService="0" />
</system.serviceModel>
...
I would create a separate interface.
Think of your interface like a real contract between two parties. You are using it to define what operations are available to a client. If it's in the contract, it's available.
Instead of looking for some sort "invisible ink" that would make certain parts of the contract available to certain clients, I'd simply create two contracts.
I'm a little confussed. The OperationContractAttribute is required. A WebGetAttribute on it's own shouldn't do anything, as the method is not expossed as an operation.
As for hiding an operation, that is not possable either. If the interface is your contract, and you definatly want two different contracts then you will need two different interfaces.
If you don't want to duplicate your code then you can still use inheritace. Have one interace define your SOAP operation Add and then inherit from that to add AddWithHttpGet. Then by targeting the different interfaces in your endpoints, the SOAP endpoint would have one operation and REST endpoint would have two.
try this you want hide webmethod form soap header in c#
[SoapDocumentMethod(ParameterStyle = SoapParameterStyle.Bare), WebMethod]
public string Operation(RIL_OB_MSG RIL_OB_MSG)
{
}

Resources