I am specifically looking for an example which use a) WCF & REST. After a long googling, though I got some but they are beyond my understanding.
Could some one please give me a very simple example say "Hallow World" or Summation of 2 numbers which will give me a clear insight about how to write a server, and also how to consume the same from the client end.
Also if any good link that explains this kind of example in simple terms kindly tell me that.
Thanks
REST in WCF is not that hard once you figure it out.
First you must define your interface.
Here is an example.
[ServiceContract]
public interface IRESTExample
{
[WebGet(UriTemplate = "interaction/queue?s={site}", RequestFormat = WebMessageFormat.Xml, ResponseFormat = WebMessageFormat.Xml)]
[OperationContract]
string QueueInteraction(string site);
[WebGet(UriTemplate = "interaction/cancel?id={interactionId}", RequestFormat = WebMessageFormat.Xml, ResponseFormat = WebMessageFormat.Xml)]
[OperationContract]
string CancelInteraction(string interactionId);
[WebGet(UriTemplate = "queue/state?s={site}&q={queue}", RequestFormat = WebMessageFormat.Xml, ResponseFormat = WebMessageFormat.Xml)]
[OperationContract]
string QueueState(string site, string queue);
}
You can see in the WebGet you define the final URL. So it depends on where you bind it, but say you bind the endpoint to www.example.com/rest
QueueInteraciton would be www.example.com/rest/interaction/queue?s=SomeSite
Where {stie} or {parameterName} is replaced with the name of the parameter.
The implemetion is just a simple class, I am going to assume you know how to implement an interface. If you need help just leave a comment.
Now binding the endpoint. In the end it is not that hard, you can do it all in the config.
<system.serviceModel>
<services>
<service name="Stackoverflow.Example.Service.RestExample" behaviorConfiguration="MyServiceTypeBehaviors">
<host>
<baseAddresses>
<add baseAddress="http://localhost:2136/RestExample"/>
</baseAddresses>
</host>
<endpoint address="rest" binding="webHttpBinding" behaviorConfiguration="xmlBehavior" contract="Stackoverflow.Example.Service.IRESTExample" />
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="MyServiceTypeBehaviors" >
<!-- Add the following element to your service behavior configuration. -->
<serviceMetadata httpGetEnabled="true" />
</behavior>
</serviceBehaviors>
<endpointBehaviors>
<behavior name="jsonBehavior">
<webHttp/>
</behavior>
<behavior name="xmlBehavior">
<webHttp/>
</behavior>
</endpointBehaviors>
</behaviors>
<bindings>
<basicHttpBinding>
<binding name = "NoSecurity">
<security mode = "None" />
</binding>
</basicHttpBinding>
</bindings>
</system.serviceModel>
Now the code to start the service and bind it. YOu can do it in anything, for example a console app.
RestExample exampleService = new RestExample();
host = new ServiceHost(exampleService);
host.Open();
This should be enough to get started.
msdn article An Introduction To RESTful Services With WCF with code example at msdn code gallery. Also check out this codeproject article
David Basarab's response is correct, but there's a much simpler way to do this without all the manual wire-up. Especially if you've used to classic ASMX web services and don't have a lot of WCF experience, the following method is dirt simple.
In a Visual Studio 2010 web project, add a reference to System.ServiceModel.Web.
Chose "add new item" in your project. The template you want is in "Web" and is called "AJAX-enabled WCF Service". Don't choose the vanilla "WCF Service"! If you do you have to do all the web.config wiring yourself that David Basarab described, and it's a pain. The "AJAX-enabled WCF Service" does all that setup for you. Name your service whatever you want.
Open up the .svc file. In the [ServiceContract] attribute on your class, fill in the Namespace string parameter with whatever you want.
You'll get a sample DoWork() method and a bunch of comments telling you what to do in the file. The trick to getting the RESTful API is to add [WebGet()] attributes to your web methods. Add one to DoWork() and verify everything functions for you.
So, to call the DoWork() method, you'd hit this in your browser:
http://localhost/MyAjaxEnabledService.svc/DoWork
Let's add a new HelloWorld() method now that shows some parameters and output.
VB:
<OperationContract()>
<WebGet(ResponseFormat:=WebMessageFormat.Xml)>
Public Function HelloWorld(ByVal name As String) As String
WebOperationContext.Current.OutgoingResponse.ContentType = "text/xml"
Return String.Format("Hello, {0}!", If(String.IsNullOrWhiteSpace(name), "world", name))
End Function
C#:
[OperationContract()]
[WebGet(ResponseFormat=WebMessageFormat.Xml)]
public string HelloWorld(String name) {
WebOperationContext.Current.OutgoingResponse.ContentType = "text/xml";
Return String.Format("Hello, {0}!", String.IsNullOrWhiteSpace(name) ? "world" : name);
}
Now you can visit:
http://localhost/MyAjaxEnabledService.svc/HelloWorld?name=MattMc3
There's a lot of crappy and confusing documentation out there about WCF, especially for those who crave the simplicity of the old .ASMX style. Hopefully this helps someone get started with WCF. There's a lot more you can do with it than the old ASMX-style, but it's hard to ramp up and not get discouraged with MS for their poor help with the transition from ASMX. You can read more about quick-and-dirty RESTful WCF services here.
If you really want to do ReST then use a web framework that will lead you down the right path. See OpenRasta.
It is not impossible to do WCF to do ReST, it is just very difficult to learn how to do Rest with a framework that will frequently get in your way and lead you in the wrong direction.
In Microsoft Web Developer, you can use the Online Template "WCF REST Service." It will set up a project for you with the correct web.config and global.asax files.
You can create an WCF REST web service by configuring your endpoint to use a webHttpBinding as seen in this in-depth tutorial:
http://www.west-wind.com/weblog/posts/310747.aspx
Here is another open source web services framework that simplifies creating XML and JSON REST web services without requiring any extra configuration.
Edit: Added link to good article articulating the spirit of REST:
http://tomayko.com/writings/rest-to-my-wife
Link to blog post comment explaining common misconceptions of REST:
http://roy.gbiv.com/untangled/2008/rest-apis-must-be-hypertext-driven
Related
Currently I'm building a central place to do some common tasks, which a bunch of projects should use and it would be extremely nice to have this (mostly for convenience, I'll admit):
I just can't seem to do that. I've tried implementing multiple interfaces, but that doesn't work the way I want. It exposes too much in the same place.
I have a pseudo thing going on right now where I have three services, but on three different addresses (/ReportingService.svc, /QueueService.scv, and /TicketService.svc) and thus the above doesn't happen (ideally just one /Services.svc).
The way the dialog is constructed seems to support this way of exposing services (namely it says "1 service(s) found at[...]"), but I just can't find a way to do it.
I suppose this could be helpful, but I haven't been able to make it work either. I just get a 404 when trying to open the listenUri.
Does anyone have any good ideas?
You need to create your methods in the interface (and obviously implement those methods in your service class).
[ServiceContract]
public interface IService
{
[OperationContract]
string method1(int code);
[OperationContract]
int method2(String id);
}
So, now you have just one service and multiple methods inside of it.
Or if you want to keep your methods organized, you could include services in your Web.config file.
<services>
<service name="ServicioWeb.IService1">
<endpoint binding="webHttpBinding"
contract="ServicioWeb.IService1"
behaviorConfiguration="WebBehavior"
/>
</service>
<service name="ServicioWeb.IService2">
<endpoint binding="webHttpBinding"
contract="ServicioWeb.IService2"
behaviorConfiguration="WebBehavior"
/>
</service>
</services>
And your URL would change a bit. Something like this:
http://localhost:8080/Service1.svc/...
http://localhost:8080/Service2.svc/...
I am having trouble adding a service to my app.config that implements two contracts, and thus needs two endpoints.
See this question for a basic example of what I am trying to do:
WCF config for a service class implementing multiple contracts on separate endpoints
I really want to use the Service Reference in my clients to create and maintain the proxies for me, but when I try to do this with a service with two endpoints, I get the following error in the details when it tries to download the metadata:
Metadata contains a reference that cannot be resolved
Here is an example of how I have the service setup in my app.config in my wcf service library:
<service name="MyService">
<endpoint address="Address1" binding="wsDualHttpBinding" bindingConfiguration=""
name="Service1" contract="IService1" />
<endpoint address="Address2" binding="wsDualHttpBinding" bindingConfiguration=""
name="Service2" contract="IService2" />
<endpoint address="mex" binding="mexHttpBinding" bindingConfiguration=""
name="mex" contract="IMetadataExchange" />
<host>
<baseAddresses>
<add baseAddress="http://localhost:8732/Design_Time_Addresses/MyService/" />
</baseAddresses>
</host>
</service>
I feel like I am missing something simple. When I remove one of the end points, everything works fine. But if I have both end points in there, it can't resolve the metadata.
I have tried removing the base address and using full addresses, and with different ports but all paths I have tried lead to the same error.
Edit:
I should clarify why I am trying to do this in the first place I guess. I have a singleton service that I would like clients to be able to connect to. But there are some methods that I do not want clients to have access to. I thought separating the admin methods and the client methods into two separate contracts would be a good start.
To be even more clear, this is a game server. I want to be able to start new instances of the game server and send it a map and things like that.
I don't want gamers to have access to methods like LoadMap() or anything like that.
I really want to separate the methods and callbacks that the game client would have versus the methods and callbacks a match making service or server admin would have.
I also would like them to be separate contracts just to make it easier to read and maintain.
However, if there is a better way to do that, I am open for suggestions.
Took me a while to figure this out. I tore down my project and started rebuilding it from the beginning until it broke.
Apparently you cannot have two callback methods with the same name in your callback contracts if you try to do this.
Example:
public interface IService1Callback
{
[OperationContract(IsOneWay = true)]
void GetDataDone();
}
public interface IService2Callback
{
[OperationContract(IsOneWay = true)]
void GetDataDone();
}
If you then set these as the callback contracts on your service contracts like this:
[ServiceContract
(Namespace = "ServiceLib",
SessionMode = SessionMode.Required, CallbackContract = typeof(IService1Callback))]
public interface IService1
{
[OperationContract(IsInitiating = true)]
string GetData(int value);
}
[ServiceContract
(Namespace = "ServiceLib",
SessionMode = SessionMode.Required, CallbackContract = typeof(IService2Callback))]
public interface IService2
{
[OperationContract(IsInitiating = true)]
string GetOtherData(int value);
}
you will end up getting the error I mentioned in my original question.
I believe this is because the end points cannot figure out which callback contract the method comes from since they have the same name, so the metadata cannot resolve the reference.
Luckily I won't have callbacks with the same name, but I was stuck on this for a while because I had just setup some dummy methods to get things going.
I create WCF service with Spring.NET framework. This service is math service
and provide some computations for client apps.
I have question about WCF service parallelization on multi-core server. For simple
example I have server with 20 cores.
First here is a simplified code.
//WS interface
public interface IMatlabService
{
List<ResultData> Calculate(byte [] data);
}
//WS class definition
[ServiceBehavior(Namespace = "http://server.com/MatlabService")]
public class MatlabService: IMatlabService
{
public IMatlabManager MatlabManager{get;set:}
//web metod for math computations
public List<ResultData> Calculate(byte [] data)
{
var result = new List<ResultData>();
//do math work in another thread
Task<List<ResultData>> task = Task.Factory.StartNew<List<ResultData>>(() =>
{
return MatlabManager.CalculateWithFiniteElementMethod(data);
});
result.AddRange(task.Result)
return result;
}
}
public interface IMatlabManager
{
List<ResultData> CalculateWithFiniteElementMethod(byte [] data);
}
public class MatlabManager : IMatlabManager
{
public List<ResultData> CalculateWithFiniteElementMethod(byte [] data)
{
// do some math work
}
}
With Spring.NET I configure web service and manager class as not singleton.
Spring.NET XML configuration is here.
Matlab manager configuration:
<object name="matlabManager"
type="MatlabManager"
singleton="false"/>
MatlabService configuration:
<object name="matlabService"
type="MatlabService"
singleton="false">
<property name="MatlabManager" ref="matlabManager"/>
</object>
WCF service configuration from web.config
<behavior name="Behavior1">
<serviceMetadata httpGetEnabled="true"/>
<serviceDebug includeExceptionDetailInFaults="true"/>
</behavior>
<services>
<service name="matlabService"
behaviorConfiguration="Behavior1">
<endpoint address=""
binding="basicHttpBinding"
contract="IMatlabService"
bindingNamespace="http://server.com/MatlabService"/>
<endpoint contract="IMetadataExchange"
binding="mexHttpBinding"
address="mex"/>
</service>
</services>
SVC file.
<%# ServiceHost Language="C#" Debug="true" Service="MatlabServiceService" Factory="Spring.ServiceModel.Activation.ServiceHostFactory" %>
I believe for each client web metod call is created new instance of
MatlabService and WCF service work is do on new thread (WCF service
thread) and OS assign this thread to CPU core.
Or I am wrong and behavior create new service object per call I must
define in ServiceBehavior property InstanceContextMode?
[ServiceBehavior(InstanceContextMode=InstanceContextMode.PerCall)]
In web method Calculate of MatlabService I use
System.Threading.Tasks for parallelization so math work is do in
another thread (Math thread).
For each call is created WCF service thread and in WCF service
thread is created Math thread.
I am not sure if this is true.
Maybe is needed allow multi-threading in WCF service in
ConcurrencyMode?
[ServiceBehavior(InstanceContextMode=InstanceContextMode.PerCall,ConcurrencyMode
= ConcurrencyMode.Multiple)]
I would like heard ideas how can parallelize web metod calls for multi core CPU.
I google it but not find any clear and usefull for me because I use Spring.NET framework for creation WCF service.
The default instance context mode is PerCall, so setting that explicitly is redundant.
Yes, you're creating an additional thread to do the math operations, but you're not gaining anything because you're blocking until the task is complete. In fact, it is less efficient because you have the overhead of creating and mangaging an additional thread.
Each web call is already serviced in its own thread.
The only place I can see to add additional parallel computing is within the implementation of:
MatlabManager.CalculateWithFiniteElementMethod(data)
However, that looks like a call to Matlab. If you can reimplement that method using parallel code, you might be able to eek out some performance gains.
Whatever you do, profiling is the key to understanding if you're actually making it faster. Remember - parallel doesn't always mean faster. There is overhead in synchronizing these operations and creating the threads for them.
Hi i am in the process of creating a restful service with WCF, the service is likely to be consumed by at least 500 people at any given time. What settings would i need to set in order to deal with this. Please give me any points and tips, thanks.
Here is a sample of what i have so far;
[ServiceBehavior(IncludeExceptionDetailInFaults = true, InstanceContextMode = InstanceContextMode.Single, ConcurrencyMode = ConcurrencyMode.Multiple)]
And this is an example of a method being called;
public UsersAPI getUserInfo(string UserID)
{
UsersAPI users = new UsersAPI(int.Parse(UserID));
return users;
}
[OperationContract]
[WebGet(BodyStyle = WebMessageBodyStyle.Bare, ResponseFormat = WebMessageFormat.Json, UriTemplate = "User/{UserID}")]
[WebHelp(Comment = "This returns a users info.")]
UsersAPI getUserInfo(string UserID);
The best approach would be to use:
InstanceContextMode.PerCall
ConcurrencyMode.Single
This will create a new instance of the service class for each caller and saves you from having to worry about multi-threaded, concurrent access to your code, since each request gets its own service class instance (which in itself is single-threaded - it serves only a single caller at a time).
Also, with this approach, you can easily "scale out", e.g. just simply add more servers to handle higher load (servers at your locations, or "in the cloud", e.g. Windows Azure workers).
Using the ServiceThrottling service behavior, you can control very easily how many concurrent callers are allowed - this depends on the type and size of your machine.
<serviceBehaviors>
<behavior name="Throttling">
<serviceThrottling
maxConcurrentCalls="16"
maxConcurrentInstances="16"
maxConcurrentSessions="10" />
</behavior>
</serviceBehaviors>
Those are the defaults for WCF 3.5 - the maxConcurrentCalls settings defines how many callers can be handled simultaneously.
Check out the MSDN docs on Service throttling for more details.
We have an application where we wish to expose an large number of database entities and some business logic. Each entity will require the ability to Read , Add, and Update. at this point we do not expect to allow deletion.
the software we build is used in a wide range of business, so of which are multi tenanted operations Bureau services, also some of our clients use this approach to have separate databases for financial reasons.
We wish to be able to minimize the number of endpoints that need to be maintained. At the moment there are only 3 tables be exposed as WCF interfaces each with 6 attached methods. this is manageable but if operation has 50 databases that suddenly becomes 150 endpoints. worse if we have 50 tables exposed that becomes 2500 endpoints.
Does anyone have a suggestion on how we could design out system that we still have a simple entity model of Job.add (var1) or iList jobs = Job.GetSelected("sql type read").
without all these endpoints
WCF Data Services allows you to expose your data in a RESTful manner using the Open Data protocal (OData). This was formally called ADO.Net data services and before that Astoria. Any IQueryable collection can be exposed. The way shown in most of the examples is to use the Entity Framework, however there are examples showing usage with NHibernate and other Data Access technologies. OData is a self describing API based on Atom-Pub with some custom extensions. With a minimal amount of code you can expose you're entire database in a well defined format. That's the easy part.
In order to implement multi-tenency, you can create query interceptors in the WCF Data Services application to implement that logic. The number of interceptors and the complexity of the code you write will depend upon your security model and requirements. Looking at something like T4 templates or CodeSmith to generate the interceptor methods based on your database schema may be a way to prevent lots of repetitive manual coding.
The link I provided has a lot of information and tutorials on WCF Data Services and would provide a good place to start to see if it would meet your needs. I have been looking at WCF Data Services for a similar problem (Multi-tenancy), and would love to hear how you evently implement your solution.
It seems like you could pass the "identity" to every query and take that into account. This would mean that every record on your "Job" table would need to have a reference to the owner "identity" but that should not be much of a problem.
Just make sure that every query validates the "identity", and you should be OK.
If I understand your question correctly, I think you need unique endpoints but you can have a single service behavior that your end points reference.
Create a default endpoint:
<behaviors>
<serviceBehaviors>
<behavior name="MyService.DefaultBehavior">
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="true" />
</behavior>
</serviceBehaviors>
</behaviors>
Set your default binding:
<bindings>
<wsHttpBinding>
<binding name="DefaultBinding">
<security mode="None">
<transport clientCredentialType="None"/>
</security>
</binding>
</wsHttpBinding>
</bindings>
Have all service reference point to the default behavior and binding:
<service behaviorConfiguration="MyService.DefaultBehavior"
name="MyService.Customer">
<endpoint address="" binding="wsHttpBinding" bindingConfiguration="DefaultBinding"
contract="MyService.ICustomer">
<identity>
<dns value="localhost" />
</identity>
</endpoint>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
</service>
Each time you add a service, its a simple config entry.
With Apache you can use a fairly simple set of URL rewriting rules to map an arbitrary set of DB table tables and their corresponding endpoints to a single endpoint with a parameter.
For example, to map $ROOT/table_name/column_name to $ROOT/index.php?tn=table_name&cn=column_name, you could add a rule like this to $ROOT/.htaccess:
RewriteRule ^([a-zA-Z0-9_]+)/([a-zA-Z0-9_]+)/?$ index.php?tn=$1&cn=$2 [QSA,L]
Then you only need to maintain $ROOT/index.php (which of course can generate the appropriate HTTP status codes for nonexistent tables and/or columns).
Providing Multi-Tenancy, Without A Bazillion End Points
One way is to go with a REST-style WCF service that can use username/passwords to distinguish which client you are working with, and thus be able to select internally which DB to connect to. WCF gives you the the UriTemplate which allows you to map part's of the URL to the param's in your web methods:
HTTP GET Request: http://www.mysite.com/table1/(row Id)
HTTP PUT Request: http://www.mysite.com/table1/(row Id)/(field1)/(field2)
HTTP POST Request: http://www.mysite.com/table1/(row Id)/(field1)/(field2)
HTTP DELETE Request: http://www.mysite.com/table1/(row Id)
You can add other Uri Templates for more tasks as well, such as the following:
HTTP GET Request: http://www.mysite.com/table1/recentitems/(number of most recent items)
HTTP GET Request: http://www.mysite.com/table1/cancelPendingOrders/(user Id)
Who's Using My Service?
By requiring clients to supply a username and password, you can map that to specific DB. And by using the UriTemplate of /{tableName}/{operation}/{params...} you could then use code in your web service to execute the DB procedures given the table, operation, and params.
Wrapping It Up
Your web configuration wouldn't need to be altered much at all even. The following web article series is a great place to learn about REST-style web services, which I believe fits what you need: http://www.robbagby.com/rest/rest-in-wcf-blog-series-index/