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 ;)
Related
I need to know if I can create a WCF service using TFTP to get data from a device. I know I can create an application using C# to do this but I am trying to make it a web based application. Also the WCF needs to be hosted on IIS. I want to use a WCF service to start a connection and then pull an image from my device. When I run my code it does not seem to have a problem with the SendTo command but it always gives me a "System.Net.Sockets.SocketException (0x80004005): A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond at System.Net.Sockets.Socket.ReceiveFrom(...). Is this because I am using a netTcpBinding? Can I do this using a basic HTTP binding or something else? Or maybe it just isn't possible to create this service using WCF, thoughts??
Service Code Snippet:
public byte[] ipTftpGet(String xferFileName)
{...
byte[] rcvBuffer = new byte[5200];
....
try
{
ipEndPointFtp = new IPEndPoint(ipAddress, 69);
tftpS = new Socket(ipEndPointFtp.AddressFamily, SocketType.Dgram, ProtocolType.Udp);
remoteEP = ipEndPointFtp;
// Request and Receive first Data Packet From TFTP Server
tftpS.SendTo(sndBuffer, nameLen, System.Net.Sockets.SocketFlags.None, remoteEP);
tftpS.ReceiveTimeout = 1000;
try
{
len = tftpS.ReceiveFrom(rcvBuffer, ref remoteEP);//tftpS.ReceiveFrom(rcvBuffer, ref remoteEP);
rcvBuffer[len] = 0x00;
}
catch (System.Net.Sockets.SocketException ex)
{
xferValid = false;
errMsgStr = ex.ToString();
}
}
Web.config:
<services>
<service behaviorConfiguration="mexBehavior"
name="ComService.ComService">
<endpoint address="ComService" binding="netTcpBinding"
contract="ComService.IComService" />
<host>
<baseAddresses>
<add baseAddress="net.tcp://localhost:8090" />
<add baseAddress="http://localhost:8080" />
</baseAddresses>
</host>
</service>
</services>
I was able to determine the problem. TFTP uses UDP and apparently you cannot use IIS to host the service. You can host the service using a Windows Console or Windows Forms application. I created a simple console application and then updated my web.config (now an App.config) as follows:
Program.cs:
namespace TFTPConsoleHost
{
class Program
{
static void Main(string[] args)
{
using (ServiceHost host = new ServiceHost(typeof(TFTPService.TFTPService)))
{
host.Open();
Console.WriteLine("Host started # " + DateTime.Now.ToString());
Console.ReadLine();
}
}
}
}
App.config:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.2"/>
</startup>
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior name="">
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="true"/>
<serviceDebug includeExceptionDetailInFaults="false"/>
<serviceThrottling maxConcurrentCalls="1000" maxConcurrentInstances="1000" maxConcurrentSessions="1000"/>
</behavior>
</serviceBehaviors>
</behaviors>
<bindings>
<netTcpBinding>
<binding name="unsecured">
<security mode="None"/>
</binding>
</netTcpBinding>
</bindings>
<services>
<service name="TFTPService.TFTPService">
<endpoint address="soap.udp://localhost:8060/" binding="udpBinding" contract="TFTPService.ITFTPService"/>
<host>
<baseAddresses>
<add baseAddress="http://localhost:8060/"/>
</baseAddresses>
</host>
</service>
</services>
</system.serviceModel>
</configuration>
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)
{
}
}
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
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
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)
{
}