WCF and ASP.NET AJAX Integration
This post is part of WCF REST Presentation I show last week at Microsoft.
I played with the WCF and ASP.NET AJAX integration, and created a sample web site which by can integrate WCF service with Microsoft Virtual Earth.
The Service Contract
The following contract is simple service contract with one method GetLocation(). The namespace "Sample.Services" will be used later as a prefix to the generated proxy.
AspNetCompatibilityRequirementsMode allows the service to use ASP.NET features, such as accessing HttpContext object or identity impersonation.
[ServiceContract(Namespace = "Sample.Services")]
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
public class MapService
{
[OperationContract]
public Location GetLocation(Target target)
{
Double latitude = 0;
Double longitude = 0;
if (target.Name == "Starbucks Manhattan")
{
latitude = 40.70456;
longitude = -74.01317;
}
Location location = new Location
{
Latitude = latitude,
Longitude = longitude
};
return location;
}
}
[DataContract]
public class Location
{
[DataMember]
public Double Latitude
{
get;
set;
}
[DataMember]
public Double Longitude
{
get;
set;
}
}
[DataContract]
public class Target
{
[DataMember]
public String Name
{
get;
set;
}
}
The Script
The interesting point here is how you access the service itself - by adding the namespace prefix (if not exist use default Tempuri.org).
You can also notice how I'm sending a complex parameter 'target' which is not a basic type, but complex - I use JSON directly .
var map;
var index = 0;
function LoadMap()
{
map = new VEMap('VEMap');
map.LoadMap();
}
function WebServiceCallBack(response)
{
AddPushPin(response);
}
function AddPushPin(point)
{
var pin = new VEPushpin(
index,
new VELatLong(point.Latitude, point.Longitude),
null,
point.Name,
point.Description);
index++;
map.AddPushpin(pin);
map.PanToLatLong(new VELatLong(point.Latitude, point.Longitude));
}
function OnGetTarget()
{
var target = { "Name" : $get("target").value };
Sample.Services.MapService.GetLocation(target, WebServiceCallBack, OnError);
}
function OnError(result)
{
alert(result.get_message());
}
Proxy Generation
Try the following URL and you will get the proxy itself:
http://localhost:49814/VirtualEarth/MapService.svc/js
Notice that the proxy created with static methods with the same signature as the methods on the service itself, and as additional, adds callback, error handler and a user context.
Type.registerNamespace('Sample.Services');
Sample.Services.MapService=function() {
Sample.Services.MapService.initializeBase(this);
this._timeout = 0;
this._userContext = null;
this._succeeded = null;
this._failed = null;
}
Sample.Services.MapService.prototype={
_get_path:function() {
var p = this.get_path();
if (p) return p;
else return Sample.Services.MapService._staticInstance.get_path();},
GetLocation:function(target,succeededCallback, failedCallback, userContext) {
return this._invoke(this._get_path(), 'GetLocation',false,{target:target},succeededCallback,failedCallback,userContext); }}
Sample.Services.MapService.registerClass('Sample.Services.MapService',Sys.Net.WebServiceProxy);
Sample.Services.MapService._staticInstance = new Sample.Services.MapService();
Sample.Services.MapService.set_path = function(value) { Sample.Services.MapService._staticInstance.set_path(value); }
Sample.Services.MapService.get_path = function() { return Sample.Services.MapService._staticInstance.get_path(); }
Sample.Services.MapService.set_timeout = function(value) { Sample.Services.MapService._staticInstance.set_timeout(value); }
Sample.Services.MapService.get_timeout = function() { return Sample.Services.MapService._staticInstance.get_timeout(); }
Sample.Services.MapService.set_defaultUserContext = function(value) { Sample.Services.MapService._staticInstance.set_defaultUserContext(value); }
Sample.Services.MapService.get_defaultUserContext = function() { return Sample.Services.MapService._staticInstance.get_defaultUserContext(); }
Sample.Services.MapService.set_defaultSucceededCallback = function(value) { Sample.Services.MapService._staticInstance.set_defaultSucceededCallback(value); }
Sample.Services.MapService.get_defaultSucceededCallback = function() { return Sample.Services.MapService._staticInstance.get_defaultSucceededCallback(); }
Sample.Services.MapService.set_defaultFailedCallback = function(value) { Sample.Services.MapService._staticInstance.set_defaultFailedCallback(value); }
Sample.Services.MapService.get_defaultFailedCallback = function() { return Sample.Services.MapService._staticInstance.get_defaultFailedCallback(); }
Sample.Services.MapService.set_path("/VirtualEarth/MapService.svc");
Sample.Services.MapService.GetLocation= function(target,onSuccess,onFailed,userContext) {Sample.Services.MapService._staticInstance.GetLocation(target,onSuccess,onFailed,userContext); }
var gtc = Sys.Net.WebServiceProxy._generateTypedConstructor;
if (typeof(Target) === 'undefined') {
var Target=gtc("Target:http://schemas.datacontract.org/2004/07/
Target.registerClass('Target');
}
if (typeof(Location) === 'undefined') {
var Location=gtc("Location:http://schemas.datacontract.org/2004/07/
Location.registerClass('Location');
}
The ASP.NET Page
<html xmlns="http://www.w3.org/1999/xhtml >
<head id="Head1" runat="server">
<title></title>
</head>
<body onload="LoadMap();">
<form id="form1" runat="server">
<asp:ScriptManager ID="ScriptManager1" runat="server">
<Scripts>
<asp:ScriptReference Path="http://dev.virtualearth.net/mapcontrol/mapcontrol.ashx?v=5 />
<asp:ScriptReference Path="mapscripts.js" />
</Scripts>
<Services>
<asp:ServiceReference Path="MapService.svc" />
</Services>
</asp:ScriptManager>
<div style='width: 800px; height: 500px; position: relative; overflow: hidden;' id='VEMap'></div>
Enter target: <input type="text" id="target" />
<input type="button" value="get target" onclick="OnGetTarget()" /><br />
<br />
</form>
</body>
</html>
The Service File
The WebScriptServiceHostFactory adds ASP.NET AJAX endpoint the the service, and all of this without a line of configuration!!
When you specify the WebScriptServiceHostFactory, it creates a ServiceHost with the appropriate binding and behavior for integration with ASP.NET AJAX.
<%@ ServiceHost Language="C#" Debug="true" Service="MapService" Factory="System.ServiceModel.Activation.WebScriptServiceHostFactory" %>
Conclusion
To summarize the WCF and ASP.NET AJAX Integration:
- Full support in client stack
- Provides proxy generation
- Supports GET and POST only
- Does not support UriTemplates
- No configuration using WebScriptServiceHostFactory
- And finally, works in ASP.NET medium trust
The source code of WCF and ASP.NET AJAX Integration.
WCF 3.5 REST Presentation
Hi,
I want to thank to C* User Group, Microsoft people and all of those who come to the presentation yesterday at Microsoft.
It was pleasurable and very beneficial, I study a lots from it, and I highly recommend for anyone who hesitated.
I'm attaching here the presentation, and I will post the code later.
WCF-REST.pptx
WCF and ASP.NET AJAX Integration
REST Friendly URLs
Thanks,
Gady.
Hi,
I'm giving a presentation tomorow about the "New HTTP Programming Model in WCF 3.5". I will talk about RESTful services, show demos on WCF, and using some known REST API's.
Some teasers:
Attached below the invitation, hope to see you there.
Gady.
Israel Visual C* Users Group May Meeting
Date: Wednesday, May 21, 17:00 - 20:00
Place: Microsoft Israel
Hapnina 2 (Amdocs Building)
Raanana
+972 (9) 762-5100
Topic: “Creating RESTful Web Services with WCF”
Lecturer: Gady Elkarif, SAP Labs, Israel
Creating RESTful Web Services with WCF
REST stands for Representational State Transfer; a term coined by one of the original authors of the HTTP protocol, Roy Fielding, in his 2000 doctoral dissertation. This session will show the power and productivity of WCF 3.5, demonstrating the new Web-centric features of WCF in the .NET Framework 3.5. The session will focus on the new web programming model features of WCF, enabling you to develop "RESTful" web services. The session starts with a brief overview of what does it mean to be "RESTful", then moves on to the new HTTP web programming model in WCF, including easy-to-use HTTP programming model, JavaScript Object Notation (JSON) messaging capabilities, and a new syndication API that makes it easy to create and consume syndicated content. Finally, the session will end with some advanced topics on developing REST API with WCF and a demonstration of using real commercial REST API (hosting a Silverlight application in Facebook).