Archive

Archive for the ‘ADO.Net Data Services’ Category

Introduction to ADO.Net Data Services (Part 3: Reading and Manipulating results in a .Net consumer application)

March 26, 2008 8 comments

NOTE: Since SP1 of .net 3.5 came out this post has become outdated. You no longer have to add the Microsoft.Data.WebClient into the project and you no longer have to create your class outside of VS and bring it in. It has become a lot easier. You can now reference the data service just like any other service in VS by add a new service reference and pointing to the data service URI. This will create the underlying model for you on the client side. I appologize for any confusion as this blog was written pre .net 3.5 SP1. Life is so much easier now!

In My last 2 blogs I have introduced ADO.Net DataServices and I have showed you how to read and manipulate the data in a browser. This blog will be a continuation of those blogs. In order to follow along in this blog you will have to minimally run through Part 1  to create the data service that will be used in this blog. I did not intend this blog to be self contained, it is part of a larger series of blogs. So, please read the first two parts of this series before attempting to work through this one. Thanks!

  1. Make sure the ADO.Net Data Service from Part 1 of this blog is running – you can do this by hooking it up in your IIS or just debugging it from Visual Studio.
  2. Open up Visual Studio 2008.
  3. Click File/New/Project
  4. Choose a Windows Forms Application and click OK. NOTE: I am showing this in a Windows Forms Application to prove a point that any .net application can be the client. You could do this in a WPF, Web Application, Silverlight App, etc….
  5. Add a reference to the Microsoft.Data.WebClient
    1. The Microsoft.Data.WebClient gets put on your computer when you install the ASP.Net Extensions
    2. It is located at %ProgramFiles%\Reference Assemblies\Microsoft\Framework\ASP.NET 3.5 Extensions
    3. Right click on the References folder and choose Add Reference…\
    4. Browse to the location of the dll and add the Microsoft.Data.WebClient.dll
  6. Next we are going to generate a new object layer classes that can be used on our client app. We are going to do this with a command line tool that is installed on the computer when you installed the ASP.Net Extensions. Microsoft will be rolling this into Visual Studio eventually, but for right now this is the best way to do this. You could do this manually by creating each class individually, but this command line tool will interrogate the Data Service to create these classes for you.
    1. Make sure the ADO.Net Data Service from Part 1 of this blog is running – you can do this by hooking it up in your IIS or just debugging it from Visual Studio.
    2. Open a Command Prompt (note to Vista users – make sure you do this as an administrator)
    3. Browse to %ProgramFiles%\Microsoft ASP.NET 3.5 Extensions
    4. Run this command: WebDataGen.exe /mode:ClientClassGeneration /outobjectlayer:AdventureWorks.cs /uri:http://localhost:61823/DemoDataService.svc
    5. Note: replace your localhost and DataService with the URI in the command above
    6. Import the generated class into your project
      1. Right click on the project and choose Add/Existing Item…
      2. Browse to %ProgramFiles%\Microsoft ASP.NET 3.5 Extensions and find the AdventureWorks.cs that was created. Then click Add.
  7. Right click on the project and choose Add/New Item…
  8. Choose a class and call the class AdventureWorksServiceProcessor.
  9. Add a using statement to the class in order to have it reference the classes created in step 6 – using AdventureWorksModel;
  10. Add a using statement to the class in order to have it reference the WebClient dll we created in step 5 – using Microsoft.Data.WebClient;
  11. Add the following member to the class – AdventureWorksEntites context;
  12. Add a constructor to the class in order to open the dataservice and set the reference to the objects.
  13. Your class should look like this now (of course, change the string in the URI to point to your localhost port and service):
  14. using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using Microsoft.Data.WebClient;
    using AdventureWorksModel;
    
    namespace WindowsFormsApplication1
    {
        class AdventureWorksServiceProcessor
        {
            AdventureWorksEntities context;
    
            public AdventureWorksServiceProcessor()
            {
                Uri serviceUri = new Uri("http://localhost:61823/DemoDataService.svc");
                context = new AdventureWorksEntities(serviceUri);
                context.MergeOption = MergeOption.AppendOnly;
            }
    
        }
    }
  15. Create some retrieve methods. For this example we are going to retrieve two different ways. The first way will be with a WebDataQuery (this is just like what we did in the browser in Part 2 of this blog). The second way will be with LINQ queries. Add them both into your class because they are doing two different things (one is querying the products and the other is querying the categories).
    1. WebDataQuery way:
    2.         public IList GetProducts(string productName, ProductSubcategory category)
              {
                  int categoryId = category.ProductSubcategoryID;
                  WebDataQuery products =
                  context.CreateQuery("/ProductSubcategory(" + categoryId + ")/Product?$filter=contains(Name,'" + productName + "') or '' eq '" + productName + "'");
                  List productsSet = new List();
                  foreach (Product p in products)
                  {
                      context.LoadProperty(p, "ProductSubcategory");
                      productsSet.Add(p);
                  }
                  return productsSet;
              }
      
      
    3. LINQ way:
    4.   public IList GetCategories()
              {
                  var ProductCategories = from c in context.ProductSubcategory
                                          select c;
      
                  return ProductCategories.ToList();
              }
      
      
  16. Create the add, update, and delete methods. In the end your AdventureWorksServiceProcessor class should look like this:
  17. using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using Microsoft.Data.WebClient;
    using AdventureWorksModel;
    
    namespace WindowsFormsApplication1
    {
        class AdventureWorksServiceProcessor
        {
            AdventureWorksEntities context;
    
            public AdventureWorksServiceProcessor()
            {
                Uri serviceUri = new Uri("http://localhost:61823/DemoDataService.svc");
                context = new AdventureWorksEntities(serviceUri);
                context.MergeOption = MergeOption.AppendOnly;
            }
    
            public IList GetProducts(string productName, ProductSubcategory category)
            {
                int categoryId = category.ProductSubcategoryID;
                WebDataQuery products =
                context.CreateQuery("/ProductSubcategory(" + categoryId + ")/Product?$filter=contains(Name,'" + productName + "') or '' eq '" + productName + "'");
                List productsSet = new List();
                foreach (Product p in products)
                {
                    context.LoadProperty(p, "ProductSubcategory");
                    productsSet.Add(p);
                }
                return productsSet;
            }
    
            public IList GetCategories()
            {
                var ProductCategories = from c in context.ProductSubcategory
                                        select c;
    
                return ProductCategories.ToList();
            }
    
            public void DeleteProduct(Product product)
            {
                context.AttachObject("Product", product);
                context.DeleteObject(product);
                context.SaveChanges();
            }
    
            public void UpdateProduct(Product product)
            {
                ProductSubcategory newCategory = product.ProductSubcategory;
                context.AttachObject("Product", product);
                context.LoadProperty(product, "ProductSubcategory");
                if (newCategory.Name != product.ProductSubcategory.Name)
                {
                    context.DeleteBinding(product, "ProductSubcategory", product.ProductSubcategory);
                    context.AttachObject("ProductSubcategory", newCategory);
                    context.AddBinding(product, "ProductSubcategory", newCategory);
                }
                context.UpdateObject(product);
                context.SaveChanges();
            }
    
            public void AddProduct(Product product)
            {
                product.rowguid = Guid.NewGuid();
                context.AddObject("Product", product);
                context.AttachObject("ProductSubcategory", product.ProductSubcategory);
                context.AddBinding(product, "ProductSubcategory", product.ProductSubcategory);
                context.SaveChanges();
            }
    
        }
    }
    
    
  18. Now you can create your WebForm however you want and call out to your AdventureWorksServiceProcessor as your Data Access layer. For example: Add a combo box onto your WebForm. Then in the code behind set the datasource for the combo box to the GetCategories method:
  19.   public partial class Form1 : Form
        {
            public Form1()
            {
                InitializeComponent();
    
                AdventureWorksServiceProcessor awsProcessor = new AdventureWorksServiceProcessor();
                comboBox1.DataSource = awsProcessor.GetCategories();
                comboBox1.DisplayMember = "Name";
            }
        }

         

Now you can play around with different form variations and call out to the methods in the AdventureWorksServiceProcessor class. Also, you could take this class to a different type of .net application (Silverlight, Web Application, WPF) and as long as you bring the AdventureWorks.cs class along and set the correct references up, it should all work just the same.

Categories: ADO.Net Data Services

Introduction to ADO.Net Data Services (Part 2: Reading and Manipulating results in the browser)

March 24, 2008 3 comments

My last blog was an Introduction to ADO.Net Data Services – Part 1: Creating a Data Service.  This blog will be an continuation of that blog, thus you need to create the data service from that blog in order to work with the things I am describing in this one.

ADO.Net Data Services can be “consumed” through HTTP Requests. Thus, we can use URI’s to read and manipulate data from ADO.Net Data Services.

  1. Make sure the ADO.Net Data Service from Part 1 of this blog is running – you can do this by hooking it up in your IIS or just debugging it from Visual Studio.
  2. When it is running you will see a webpage that should look similar to this:
    1. NOTE: as I stated in Part 1 of this blog there are a couple reasons the webpage might not look like this. The most common is your browser has RSS turned on. Turn off your RSS feeds to see the xml properly. The reason for this is because ADO.Net Data Services exposes the data in ATOM by default and the browser is interpreting that as RSS.
    2. What you are technically looking at here is xml that denotes all the collections in your object model. It has wrapped these objects in “collections” to show that there can be more than one entry for each. For example: The database had a table called “Employee”, thus the object model has a collections of Employees.
  3. capture.jpg
  4. So far all you have seen is the outer most collections of all the entities in the model. So, next we will show how to dig into some of the collections. We will do this with URI manipulation only.
      1. Note: my site is running under localhost:61823 so you will have to change that to whatever your site is running under. Also, I called my service DemoDataService, you will have to change that to whatever the name of the service is that you created in Part 1.
      2. What we have just done above is told the browser that we want to see the Product entity set of the data service. This is just like writing a query against the Product table in the database to return everything.
      3. capture8.jpg
      4. Notice that it has exposed all of the properties of the products. Plus it shows you all of the inner collections of the products through the “<link” nodes.
    1. As you can see above we can dig into the service deeper and deeper by knowing what to put in our URL. Also, you can figure out what to put in the URL just by looking at its structure and figuring it out. Below is a list of other commands you should try to see what is possible (Note: I am not showing all of the commands possible, just a few to show you the power of this technology):
      1. http://localhost:61823/DemoDataService.svc/Product(1) – This shows the product with the primary key of 1 or the product with an index of 1. This shows you how to get a single entity out of the entity set.
      2. http://localhost:61823/DemoDataService.svc/Product(1)/BillOfMaterials – This shows you how to get the BillOfMaterials entity set (collection) that is associated with product one. Notice, you can traverse down the entity tree just by using / and the next entity set. Also notice that if you go back to http://localhost:61823/DemoDataService.svc/Product(1) you will see that it has a line that says <link rel=”related” title=”BillOfMaterials” href=”Product(1)/BillOfMaterials” mce_href=”Product(1)/BillOfMaterials” type=”application/atom+xml;type=feed” />. This is showing you that Product(1) has an inner collection (as known as entity set) called BillOfMaterials. You know this because the “<link” stands for an inner collection (entity set).
      3. http://localhost:61823/DemoDataService.svc/Product(1)/ProductNumber – This shows a single property from Product 1.
      4. http://localhost:61823/DemoDataService.svc/Product?$filter=MakeFlag eq true – This will filter the Product entity set down based on all products that have the MakeFlag property set to true.
      5. http://localhost:61823/DemoDataService.svc/Product?$filter=MakeFlag eq true&$orderby=SellEndDate – This will order by the SellEndDate property. It also shows you that you can append multiple operations in your URL calls.
      6. http://localhost:61823/DemoDataService.svc/Product?$top=10 – This shows you how you can do paging in your entity set retrieves
      7. http://localhost:61823/DemoDataService.svc/Product?$expand=BillOfMaterials – This one is really interesting. The Data Service uses lazy loading (basically it doesn’t load up the inner entity sets unless asked to). So, this is how you can load up an inner entity set at the same time. In this example, we want it to actually load the data for the BillOfMaterials within each Product.

Now that you have seen some of the retrieval functionality, through URIs, that the ADO.Net Data Services has to offer, I am going to show you some of the other possibilites it has. To continue following along with this blog you will need Fiddler or an equivalent HTTP tool. Fiddler is a free Web Debugging tool and can be found at http://www.fiddlertool.com/fiddler/.

I am going to use Fiddler to show you how ADO.Net Data Services is just HTTP and how it responds to header information. The reason I am using Fiddler is to prove the point that ADO.Net DataServices interaction is pure HTTP request. There is nothing else going here like some other protocols such as SOAP. I am not saying this is a good or a bad thing, it is just important to understand the simplicity of ADO.Net DataServices in how they relate to the internet.

  1. Click on the RequestBuilder in Fiddler.
  2. Place your URL into the RequestBuilder and make sure it is set to GET. For this example I am going to place the URL in for the Product entity set: http://localhost:61823/DemoDataService.svc/Product
  3. capture1.jpg
  4. Hit the Execute button.
  5. After the excute has finished it will place a new row in the Web Sessions. Double Click on that row.
  6. capture2.jpg
  7. After the results have been returned, click on the Raw tab, this will show you the header information plus the content of the request.
  8. capture3.jpg
  9. Notice, in the header, the “Content-Type” is set to application/atom+xml. This is the default request content type for ADO.Net Data Services. However, this is easily changed by setting some request headers.
  10. Go back to the RequestBuilder in Fiddler.
  11. This time type in “Accept: application/json” into the request header section.
  12. capture4.jpg
  13. Now click Execute, double click on the web session that was just executed, and go back to the RAW view of the response.
  14. Notice that the Content-Type is now “application/json” and the response content is in json format.
  15. capture5.jpg
  16. JSON is a very power javascript object notation language. This makes it very easy to write javascript code and thus makes it really easy to right Rich Internet Applications that take advantage of things like AJAX.

So, what we just showed is that the client can actually tell the server how it wants to view the information just by setting some information in the Request Header of the http call. This is very powerful, because most services just present the content in one format. ADO.Net Data Services present the information in multiple formats and lets the client determine how it wants the information presented. Currently, ADO.Net Data Services supports ATOM (XML) and JSON. It is reported that Microsoft is working on supporting a more generic XML format also (but it is not out in the extension package as of now).

It is important to note that I only showed a “GET” command here – which does a retrieve. This is because that has the most complexity in setting up the URL commands. However, you can update, delete, and add through the ADO.Net DataServices also. To do this you use regular request processes:
GET – Retrieve
POST – Create
PUT – Update
DELETE – Delete

This is the second part of this blog series. The last part will be Part 3 –  Reading and Manipulating ADO.Net Data Services results in a .Net consumer application. In this last part I am going to show how to use .net as the client application (in contrast to this blog where I showed how to use a browser as the client application). However, it is important to note, that everything I did in this blog was through standard HTTP and header calls. So, any web application can use these techniques to call out to a Data Service. But, like any good .Net application, they made it really easy to work with these in the .Net client apps (WPF, Winforms, Web Applications, etc…). So, my last post will show how to easily work with this stuff in a .Net client application.

Categories: ADO.Net Data Services

Introduction to ADO.Net Data Services (Part 1 – Creating a Data Service)

March 21, 2008 18 comments

ADO.Net Data Services (codename: Astoria) is a feature that allows users to find, manipulate, and deliver data through the use of simple URIs. This allows easy access to data over the web and allows separation of business and data logic. The concept comes from a general programming concept referred to as REST.

As of right now, ADO.Net Data Services is available in an “Extension” to .net 3.5. Eventually it will be part of the .net 3.5 sp1 framework. However, for now, you have to do some extra steps to install it (i.e.: install the asp.net extension preview).

This series of blogs is intended to do a walkthrough of creating ADO.Net Data Services and consuming them in client applications. I have written these blogs as reference material to Code Camp speeches I am doing throughout the D.C/NoVa/Md area. These blogs are not intended to describe the benefits or the why’s of ADO.Net Data Services, they are just intended to show how to work with a simple example.

I will list below the environment setup, that is needed right now, to get ADO.Net Data Services working on your computer.

  1. Supported Operating Systems – Windows Server 2003, Windows Vista, Windows XP
  2. .Net Framework 3.5
  3. Visual Studio 2008 or Visual Web Developer 2008 Express Edition
  4. ASP.Net Extensions Preview –http://www.microsoft.com/downloads/details.aspx?FamilyId=A9C6BC06-B894-4B11-8300-35BD2F8FC908&displaylang=en (PLEASE NOTE: as of today 3/21/2008 the Extensions are the way to use this feature, but soon Microsoft will role this into .net 3.5 sp1. So, if you are reading this blog after .net 3.5 sp1 comes out, you might not have to do this step)
  5. OPTIONAL – SQL Server 2005 and the AdventureWork Database. This is just needed for the example I will be writing about in this blog. This is not needed for ADO.Net Data Services. The backend database is irrelevant to work with Data Service (as long as .net can work with it). The AdventureWork Database is just Microsofts example database and it is easy for me to use to show people how to work with ADO.Net DataServices in this blog.

After your computer is setup correctly you can start building the ADO.Net Data Service. Below I will write up a simple example of leveraging the ADO.Net Data Service, as well as the Entity Framework to display a database in a RESTful manner over a web page.

  1. Open up Visual Stuido 2008.
  2. Click File/New/Project…
  3. Choose a Visual C#/ASP.NET Web Application (use C# for this example, it can be VB or any other language, but I am writing this blog assuming c#)
  4. Delete the Default.aspx that was automatically created.
  5. Right click on the WebApplication project and click Add/New Item…
  6. Choose an ADO.NET Entity Data Model and click Add
    1. The Entity Data Model is another new feature of .net that builds out an entire data access/object model for you.
    2. It is very powerful and we are going to take advantage of some of its features for this demo, but I recommend you looking into it more as it is a great new feature of .net.
    3. NOTE: I am using the Entity Data Model for this example because of how easy it is. However, you can create your own custom objects, with your own custom data access if you want. You just have to make sure the objects implement IQueryable.
  7. A Wizard will come up
    1. Make sure Generate from database is selected and click Next
    2. Create a Connection to your database (if one doesn’t already exist) throug the New Connection… button.
      1. Make sure your Data source is SQL Server
      2. Choose your Server name
      3. Choose your Authentication to the database
      4. Select the AdventureWorks database (note: this will only be there if you have installed it, if it is not there Microsoft makes this database available over the internet).
    3. Click Next
    4. Uncheck Views and Stored Procedures – thus leaving Tables as the only checked entity to use, click Finish.
    5. Congratulations! You just created an entire object model and data access layer, based off your database. It is that easy to work with the Entity Framework.
  8. Right click on the WebApplication project and click Add/New Item…
  9. Choose the ADO.NET Data Service.
  10. Lastly, we need to expose the object we created before (with the Entity Framework) to the web in this new Data Service. To do this we need to do two things. Both of these things are represented in the code block below.
    1. Tell the service which object to use. This is the object we put in the WebDataService<….> inheritence of the class.
    2. Tell the service which parts of the object should be visible. We are going to make * visible (which means everything). This is the line we put in the Intialize Service.
    3. 
          public class WebDataService1 : WebDataService< AdventureWorksModel.AdventureWorksEntities >
          {
              // This method is called once during service initialization to allow
              // service-specific policies to be set
              public static void InitializeService(IWebDataServiceConfiguration config)
              {
                  config.SetResourceContainerAccessRule("*", ResourceContainerRights.All);
              }
      
              // Query interceptors, change interceptors and service operations go here
          }
  11.  We have just successfully exposed our data through a DataService. Now you can right click on your svc file and set it as the Start Page. Then you can debug your service (F5) to see what you have created.
  12. A WebPage should come up and you should see xml similar to below:

capture.jpg

 NOTE: If you don’t see something similar to what is above there are 3 reasons:

  1. The extensions and all the prerequisites are not installed correctly on your computer
  2. The instructions were either not followed correctly, or I messed up somewhere (it is possible, but I have ran through them a bunch).
  3. You have RSS feeds turned on in your internet browser. If this is the case the webpage will look more like an RSS feed than an XML blob. To turn RSS feeds off go to your tools/options of your browser. Find the Feeds/Settings (this will be different for every browser). Turn off the Automatically marking of feeds when reading feeds (this will be stated differently for every browser).

This is part one of this blog. There will be 2 more parts:
Part 2: Reading and Manipulating ADO.Net Data Services results in the browser
Part 3: Reading and Manipulating ADO.Net Data Services results in a .Net consumer application

Categories: ADO.Net Data Services