CHAPTER 9 WCF DATA SERVICES 213 Hello WDS OK, we are now ready to work with our data service. 1. Right click on MovieService.svc and select Set As Start Page. 2. Press F5 to run your application. If all is well then you will see a screen similar to Figure 9-7 showing an XML representation of our EF classes: Figure 9-7. Output from accessing our test service Querying WCF Data Services WCF Data Services uses the URL to pass query parameters. For example, to retrieve the film entities, add /Films to the end of the existing URL (for example, http://localhost/Chapter9/MovieService.svc/Films). You should then be returned a list of all the films in AtomPub format (Figure 9-8): CHAPTER 9 WCF DATA SERVICES 214 Figure 9-8. Returning all the films from the database Having all the data returned at once isn’t too useful, so WDS supports a number of different query operators that all work with the URL. I have listed some commonly used methods in Table 9-1, but for a full list please refer to http:// msdn.microsoft.com/en-us/library/cc907912.aspx. CHAPTER 9 WCF DATA SERVICES 215 Table 9-1. List of Common Query Operators Action Operator Get film with ID 3 Films(3) Select Film where FilmID is equal to 3 Films?$filter=FilmID%20eq%203 Get FilmName field from first FilmShowing FilmShowings(1)/Film/Title Get film showings for first film Films(1)/FilmShowings Display orders by order date Orders?$orderby=OrderDate Order list of films in descending order Orders?$orderby=OrderDate%20desc Select top two orders Orders?$top=2 Skip first orders and select next two Orders?$skip=1&top=2 When working with WCF Data Services you should note the following: • Objects are case sensitive. Film is not the same as film (grrrrr!). • The query needs to be URL-encoded, so spaces must be encoded as %20. • Note the use of the ? query string character and $ to specify options. IS THERE A WAY TO LIMIT THE AMOUNT OF RECORDS RETURNED? Yes—when you are using WCF Data Services version 1.5. Please refer to the VS2010/.NET 4.0 changes section below. Security in WCF Data Services WDS allows you to fine-tune access to individual entities. For example, open MovieService.cs and find the line that reads: config.SetEntitySetAccessRule("*", EntitySetRights.AllRead); This code allows read-only access to all entities (defined by the *). If you wanted to enable full access to everything (generally a very bad idea, but useful for testing) then you can change this to: config.SetEntitySetAccessRule("*", EntitySetRights.All); WARNING If you do this anyone who can access the data service will have full access. CHAPTER 9 WCF DATA SERVICES 216 Permissions can be applied to individual objects by specifying them by name. The following line of code will enable full access to the Film entity. config.SetEntitySetAccessRule("Films", EntitySetRights.All); We will need full access to the Film entity in a few minutes, so add the previous line to MovieService.cs. Query Interceptors Sometimes you might want to intercept the user's query to apply additional logic to it (for example, to filter depending on the current user). WDS allows you to do this through query interceptors. The following example demonstrates applying this technique to any films requests to only allow those where FilmID equals 1. Add the following code to MovieService.svc: using System.Linq.Expressions; [QueryInterceptor("Films")] public Expression<Func<Film, bool>> FilterOnlyShowFilmID1() { return f => f.FilmID==1; } Returning Results in Different Formats WDS services can return data in the following formats: • AtomPub • JSON • XML AtomPub is the default format that is returned, and from WDS 1.5 you have control over how elements are mapped to AtomPub elements. Let’s look at how to return results in JSON format using jQuery and then how to access an WDS service from a console application. Using JSON with JavaScript JSON is a format commonly used by web applications since it is much less verbose than XML. JSON is also understood by many JavaScript frameworks and libraries. If you want to have WCF Data Services format your results as JSON, simply set the Accept header to application/json when making a request. The following example shows how to use jQuery to retrieve the title of the first film in the set (for more information on jQuery please refer to Chapter 12): <script> function getMovieTitle() { $.ajax({ type: "GET", dataType: "json", CHAPTER 9 WCF DATA SERVICES 217 url: "MovieService.svc/Films(1)", success: function (result) { alert(result.d.Title); }, error: function (error) { alert('error '); } }); } </script> <input type="button" Value="Get Movie Title" onclick="javascript:getMovieTitle();" /> But what JSON data will be returned by making the previous call? By using a web debugging proxy called Fiddler (www.fiddlertool.com) you can see what is returned. The following code shows the raw JSON: { "d" : { "__metadata": { "uri": "http://localhost/Chapter9/MovieService.svc/Films(1)", "type": "Models.Film" }, "FilmID": 1, "Title": "Kung Fu Panda", "Description": "Classic martial arts tale", "Length": 120, "FilmShowings": { "__deferred": { "uri": " http://localhost/Chapter9/MovieService.svc/Films(1)/FilmShowings" } } } } Notice how the results were wrapped by an object called d. This is to prevent Cross Site Request Forgery (CSRF) (see Chapter 11 for more details on this). Using JSON with C# The following code shows how to retrieve results formatted as JSON using the HttpWebRequest class in C#: System.Net.HttpWebRequest Request = (System.Net.HttpWebRequest)System.Net.HttpWebRequest.Create( "http://localhost/Chapter9/MovieService.svc/Films(1)" ); Request.Method = "GET"; Request.Accept = "application/json"; System.Net.HttpWebResponse Response = (System.Net.HttpWebResponse)Request.GetResponse(); using (System.IO.StreamReader sr = new System.IO.StreamReader(Response.GetResponseStream())) { Console.WriteLine(sr.ReadToEnd()); } Console.ReadKey(); . RECORDS RETURNED? Yes—when you are using WCF Data Services version 1.5. Please refer to the VS 201 0/ .NET 4. 0 changes section below. Security in WCF Data Services WDS allows you to fine-tune access. formatted as JSON using the HttpWebRequest class in C#: System .Net. HttpWebRequest Request = (System .Net. HttpWebRequest)System .Net. HttpWebRequest.Create( "http://localhost/Chapter9/MovieService.svc/Films(1)". Get film with ID 3 Films(3) Select Film where FilmID is equal to 3 Films?$filter=FilmID%20eq% 203 Get FilmName field from first FilmShowing FilmShowings(1)/Film/Title Get film showings for