This how-to post will introduce you to building REST-based services using WCF. This series is split into three parts. Each part is built on the previous part. Here is a link back to Part 1 if you need a refresher.
WCF in .NET 3.5 also supports returning JSON serialized data from REST-based Web Services. This makes consuming services from AJAX clients simpler and more efficient than XML. In this post, we will create a new service that returns JSON-formatted director data for use from an ASP.NET page.
Continuing from Part 1:
Right-click on the project in the Solution Explorer and select Add New Item.
Select Ajax-enabled WCF Service as the template, and name the file DirectorJSONService.svc. Click Add.
Open the DirectorJSONService.cs file (in the Solution Explorer - under App_Code).
Remove all the code and comments inside of the DirectorJSONService class (everything inside of the two curly braces).
Add a method to the DirectorJSONService named GetAllDirectors that returns an array of DirectorResult objects. The code can be the same as the method on the XML Service.
[OperationContract] [WebGet()] public DirectorResult[] GetAllDirectors() { MovieDataDataContext dc = new MovieDataDataContext();
string currentUrl = WebOperationContext.Current.IncomingRequest.UriTemplateMatch.RequestUri.ToString();
var result = from aDirector in dc.directors select new DirectorResult { DirectorName = aDirector.director_name, Link = String.Format("{0}{1}", currentUrl, aDirector.director_name) };
return result.ToArray(); }
[OperationContract] public DirectorDetail GetDirector(string director) { MovieDataDataContext dc = new MovieDataDataContext();
var result = from aDirector in dc.directors where aDirector.director_name == director select new DirectorDetail { DirectorName = aDirector.director_name, Movies = new MovieList( (from movie in aDirector.movies select movie.movie_name) ) };
return result.First(); }
Select AJAX Web Form as the template, and name the file ShowDirectors.aspx. Click Add.
Open the ShowDirectors.aspx file.
Expand the ScriptManager element, add a Services element, and add an ending ScriptManager element.
<asp:ScriptManager ID="ScriptManager1" runat="server" > <Services> </Services> </asp:ScriptManager>
Add an asp:ServiceReference element under Services - with a Path attribute value of ~/DirectorJSONService.svc.
<asp:ScriptManager ID="ScriptManager1" runat="server" > <Services> <asp:ServiceReference Path="~/DirectorJSONService.svc" /> </Services> </asp:ScriptManager>
After the ScriptManager end tag, add a select element with an id attribute with a value of "_directors". Add the onchange attribute and set its value to "directorChanged()" (this is a reference to a JavaScript function we will create later). Add an option element within the select element with a value attribute of "0" and text of "Select a director...".
<select id="_directors" onchange="directorChanged()"> <option value=0>Select a director...</option> </select>
After this select element, add an hr element, and then another select element with the value of "_movies".
<hr /> <select id="_movies"> </select>
Find the script element near the top of the ShowDirectors.aspx page.
After the end of the pageLoad function, add a function named loadDirectors that takes a parameter named results. Get a reference to the _director select element and loop through the results (this will be a JSON-encoded version of the DirectorResult array) and populate the list of movies.
function loadDirectors(results) { var dropDown = $get("_directors"); var theOption = null; for(var i = 0; i < results.length; i++) { theOption = document.createElement("OPTION"); theOption.text = results[i].DirectorName; theOption.value = results[i].DirectorName; dropDown.add(theOption); } }
Inside of the pageLoad function, call DirectorJSONService.GetAllArtists and pass the loadDirectors method to the function. (Note that we will be getting IntelliSence for the DirectorJSONService type).
function pageLoad() { DirectorJSONService.GetAllDirectors(loadDirectors); }
Save all files, then right-click on ShowDirectors.aspx in the Solution Explorer and select View in Browser.
Click the Enable Logging checkbox in Internet Explorer and refresh the page.
Double-click on the last URL in the Web Developer Helper to see the request made by the AJAX code in the page for the JSON service.
In the lower pane of the HTTP Log Viewer dialog box, click the Response Content tab. Change the View from JSON to Text to see the raw JSON content.
Close the dialog box. Leave Internet Explorer running.
In Visual Studio 2008, open the ShowDirectors.aspx file.
In the script element, add a function named directorChanged. In this method, get both select elements ("_directors" and "_movies"). Get the current value of the "_directors" select element. Reset the "_movies". Use the GetDirector method ont he DirectorJSONService and pass the value of the "_directors" select and a token of loadMovies:
function directorChanged() { var dropDown = $get("_directors"); var director = dropDown.value; var dropDown2 = $get("_movies"); dropDown2.options.length = 0; if(director != 0) { DirectorJSONService.GetDirector(director, loadMovies); } }
Create a loadMovies function that takes a parameter named results. Implement this function by looping through the Movies property of the result parameter (this will be a JSON-encoded version of the DirectorResult type). Save the ShowDirectors.aspx file when done.
function loadMovies(results) { var dropDown = $get("_movies"); var theOption = null; for(var i = 0; i < results.Movies.length; i++) { theOption = document.createElement("OPTION"); theOption.text = results.Movies[i]; theOption.value = results.Movies[i]; dropDown.add(theOption); } }
Go back to Internet Explorer and refresh the page. You will be able to change the value of the director selected, and the movie should change. You can use the Web Development Helper to view the interaction with the Service.
In this post we used the WCF .NET 3.5 Web Programming Model to create a Service that returned JSON-encoded data to make programming against WCF from AJAX based clients easier.
Nice series on wcf ajax services . Do you know of an an easy way to get around the cross site limitation. I have my aspx pages on one server and my wcf services on another server. This throws access denied errors. I have tried to setup a wcf router but it didn't work with the webhttpbinding. Any direction would be great. Thanks
My first thought would be a permissions issue. Are the servers on the same domain? I would also look at the account IIS is running under.
It is more an IE issue. The xmlhttp request is getting the "access is denied". The services would be on something like services.domain.com and aspx pages would be on web.domain.com.
Aqil,
It sounds like you could use the Bridge Provider found in the ASP.NET Futures. I have included a link to download the latest futures. http://www.microsoft.com/downloads/details.aspx?FamilyId=A5189BCB-EF81-4C12-9733-E294D13A58E6&displaylang=en
There is also an interesting article that looks just like the situation you are facing. Here is the link to the article: http://dotnetslackers.com/columns/ajax/MashitUpwithASPNETAJAX.aspx