in Silverlight

ADO.NET Data Service (Astoria) in Silverlight 2 (beta1)

Download : SL2Astoria.zip (1.21 MB)

vs-design-view.jpg

Content

  • Introduction
  • Background
  • Creating database in SQL 2005
  • Creating Silverlight project and ADO.NET Data Service in Visual Studio 2008
  • Creating a XMLHttpRequestWrapper class
  • Inserting new record in Silverlight
  • Updating the existing record in Silverlight
  • Retrieving the record from Database in Silverlight
  • Deleting the record in Silverlight
  • FAQs

Introduction

This post is written for those who like to use Astoria in Silverlight 2 before Astoria Team release the new version of Astoria Silverlight add-on. This post will guide you how to insert new record to database, how to update, retrieve or delete the existing records from the database using ADo.NET Data Service (Astoria) in Silverlight 2. You all know that Astoria Client addon for SL 2 (beta1) is not compatible with SL2beta1 and the next verion of Astoria Client addon won’t be available until end of April so that I can’t use that addon in this post either. but I will use XmlHttpRequest wrapper instead of Astoria client add-on for consuming Astoria from Silverlight. (Thanks to Jackbone from Silverlight forum for contributing very light-weight XmlHttpRequest wrapper code.).

As this post is focusing on how to do CRUD operations with Astoria in SL, I’m not gonna include other markups or animation in this post. I hope it would be easier for you to read the code that you really need.

Background

As I wrote a few articles about how to use Astoria in Silverlight 1.1 Alpha here and here, desopedr (one of my reader of my blog) and a few friends asked me how to use Astoria in Silverlight 2 (beta1).

  • The first attempt was simple. I tried to use Astoria add-on in Silverlight project but it didn’t work. When I read the Astoria forum, I found that the current version of Astoria addon doesn’t work with SL2b1. (You can read about that here and here.)
  • Secondly, I tried to use Web Client to do CRUD operations with Astoria in SL. I could successfully retrieve the data from Astoria service by using WebClient but we can’t make httpPost request or etc with WebClient so that the operations (e.g. insert) that requires other http verbs (e.g. POST, PUT, DELET) can’t be done with WebClient. So, the second attempt was failed too.
  • Then, I tried using HttpWebRequest to invoke Astoria service from Silverlight. but whenever I tried to invoke, I always get “null” for response. I’m not sure whether this is Silverlight issue or not. I posted this issue in forum and you can read this issue here.
  • After the third attempt was failed, I got the idea to invoke the service using XmlHttpRequest object from Javascript. then, Jackbond posted the Silverlight XmlHttpRequest Wrapper in our forum. (You can read the original post here.) So, I decided to use his wrapper instead of pure Javascript. After spending some times, I can successfully CUD operations with that wrapper. (I have a few problems in updating so that I’m not able to include about this for now. but I will update once I got the solution.) In this article, I will share you how to do CUD operations with Astoria in Silvrlight 2 beta1.

Creating database in SQL 2005

You have to create one table called Products with the following structure below. I have written so many time how to create a database and table in SQL 2008 so I ain’t gonna repeat here again. Please read “Creating the database in SQL 2005″ section of this post if you don’t know how to create the table.

table.jpg

Creating Silverlight project and Astoria Service in Visual Studio 2008

1. Create new project with the name “SL2Astoria” in VS 2008.

new-project-thumb.jpg

2. Attach ASP.NET project with Silverlight.

add-silverlight.jpg

ADO.NET Entity Data Model

1. Right-click on ASP.NET project and Select “Add New Item”.

2. Choose “ADO.NET Entity Data Model” and Click “OK” button

edm.jpg

3. The following dialog will be shown (It’s asking where you want to put EDM.) Click “Yes” button

app_code.jpg

4. Choose “General” and Click “Next” button

emd-wizard.jpg

5. Select the connectionstring if you already have. If there is nothing shown in connection, please click “New Connection” to create new connection. After that, click “Next” button

choose-your-data-connect.jpg

6. Unchecked all objecs first and select the table that you want. (In my case, I checked the table named “Products” only and unchecked all other tables, views and stored procedures.)

choose-your-database-object.jpg

7. Click “Finish” button.

ADO.NET Data Service

1. Right-click on ASP.NET project and Add “ADO.NET Data Service”

adonet-data-service.jpg
2. Change the sourcecode as below in WebDataService.cs. First thing we need to do is that we have to set our data model class in WebDataService. In my case, MyStoreModel.MyStoreEntities is the data model class. Then, enable the operations from our data service . Note that it’s just for testing purpose. You should not enable all operations in production.

public class WebDataService : WebDataService<MyStoreModel.MyStoreEntities>
{
// This method is called once during service initialization to allow
// service-specific policies to be set
public static void InitializeService(IWebDataServiceConfiguration config)
{
// TODO: set rules to indicate which entity sets and service operations are
// visible, updatable, etc.
// (for testing purposes use "*" to indicate all entity sets/service
// operations, but that option should NOT be used in production systems)

// Example for entity sets (this example uses "AllRead" which allows reads but not writes)
config.SetResourceContainerAccessRule("*", ResourceContainerRights.All);

// Example for service operations
config.SetServiceOperationAccessRule("*", ServiceOperationRights.All);

}

// Query interceptors, change interceptors and service operations go here
}

That’s all we need to do in ASP.NET project.

Creating a XMLHttpRequestWrapper class

XMLHttpRequestWrapper class is just a wrapper class of Javascript XmlHttpRequest object. If you are familiar with Ajax, I’m sure that you have good understanding about this object. In my example, this wrapper class is just like the way that we wrote in Javascript except I used C# instead of Javascript.


using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Windows.Browser;
using System.Text;
using System.Xml;
namespace SL2Astoria {
/// <summary>
/// Ref: http://silverlight.net/forums/t/11508.aspx
/// </summary>
public static class XMLHttpRequestWrapper {
static ScriptObject _xmlHttpRequest;

public static void DoPost(Uri url, string httpVerb) {
DoPost(url, httpVerb, string.Empty);
}
public static void DoPost(Uri url, string httpVerb, string param) {
_xmlHttpRequest = HtmlPage.Window.CreateInstance("XMLHttpRequest");

_xmlHttpRequest.Invoke("open", httpVerb, url, false);
_xmlHttpRequest.Invoke("setRequestHeader", "Content-Type", "application/json");

if (param == string.Empty) {
_xmlHttpRequest.Invoke("send");
}
else {
_xmlHttpRequest.Invoke("send", param);
}
}
}
}

CRUD operations with Astoria in Silverlight

After creating this wrapper class, we can start writing the code for CRUD operations with Astoria. but before that, you should understand which http verbs we will use for each operation. Please take a look at the table below.

Operations HTTP verbs
Insert POST
Retrieve GET
Delete DELETE
Update PUT

Inserting new record in Silverlight

We will start with inserting new record to database. In order to insert new record, we have to make Http POST request to Astoria Data Service. We will pass the data as a JSON object to that service. Yes. I hard-coded the service URL in my code. It’s just a sample, right? I’m not showing the best practice of using Silverlight. I’m just showing how to use XmlHttpRequestWrapper class to deal with Astoria. ProductName from json object is the property of entity set of Astoria and it’s also the column name of “Products” table.

string productName = "ComponentOne Silverlight Studio";
string serviceURL = "http://localhost:52976/SL2Astoria_Web/WebDataService.svc/Products/";

string jsonString = "{" + Environment.NewLine;
jsonString += "ProductName:\"" + productName + "\"" + Environment.NewLine;
jsonString += "}" + Environment.NewLine;

XMLHttpRequestWrapper.DoPost(new Uri(serviceURL), "POST", jsonString);

Updating the existing record in Silverlight

[As I told you earlier, I'm having some problems in updating. I will update this post once I got the solution. Please keep on watching.]

Retrieving the record from Database in Silverlight

Currently, there are two way to retrieve the data from Astoria in Silverlight. You can use either WebClient or XmlHttpRequestWrapper class.

string serviceURL = "http://localhost:52976/SL2Astoria_Web/WebDataService.svc/Products?$orderby=ProductID";

string result = XMLHttpRequestWrapper.DoPost(new Uri(serviceURL), "GET");

The following code is the same as the code above. But It uses WebClient instead of XmlHttpRequestWrapper.

void retrieveButton_Click(object sender, RoutedEventArgs e) {
try {

string serviceURL = "http://localhost:52976/SL2Astoria_Web/WebDataService.svc/Products?$orderby=ProductID";

////retriving data
WebClient astoriaService = new WebClient();
astoriaService.DownloadStringCompleted += new DownloadStringCompletedEventHandler(AstoriaService_DownloadStoriesCompleted);
astoriaService.DownloadStringAsync(new Uri(serviceURL));
}
catch (Exception ex) {
Console.WriteLine(ex.Message);
}
}

void AstoriaService_DownloadStoriesCompleted(object sender, DownloadStringCompletedEventArgs e) {
if (e.Error == null) {
DisplayProducts(e.Result);
}
}

Deleting the record in Silverlight

The following code is for deleting the existing data from database. All we need to do is that we specify the id of project in service URL and send the HTTP DELETE request to Astoria to delete that record.


string serviceURL = "http://localhost:52976/SL2Astoria_Web/WebDataService.svc/Products(18)/";
XMLHttpRequestWrapper.DoPost(new Uri(serviceURL), "DELETE");

FAQs

1. I have downloaded the sample. How can I run this sample?

There is MyStore.mdf in SQL Database folder. You should attach this database to MS SQL in your machine. Then, you need to change the connection string in ASP.NET project.

2. Why did you hard-code the service URL?

Yes. I hard-coded the service URL in my code. It’s just a sample, right? I’m not showing the best practice of using Silverlight. I’m just showing how to use XmlHttpRequestWrapper class to deal with Astoria.

3. Why don’t you make nice-looking UIs in your sample? Are you just lazy?

No. I have been trying to do this since last week. As I told you in “Background” section of this article, I have tried a lot of ways and I faced a lot of problems during these days. Until now, I still have some problems in updating. but I know that there are some people (e.g. desopedr ) is waiting to know how to do CRUD operations with Astoria in Silverlight. So, I just make this sample and I wrote this article in very short and limited time. I hope I will be able to create another sample with nice-looking UIs in future.

Another thing is that I just want to focus on the functionality. If I put a lot of controls, animation and etc, there will be a lot of codes for reader to look at. So, I made this sample with the code that are required only.

4. Does it support cross-domain?

No. This wrapper has exactly the same limitations as what XmlHttpRequest object has. Another thing is that invoking the Astoria data service is not in async-mode. However, you can change it easily if you want.

That’s all. I hope you might find it useful. Feel free to let me know if you have any problem or comment. Thanks.

Leave a Reply

17 Comments

  1. Hi,

    I get the following error when deleting or updating

    An exception of type ‘System.ArgumentException’ occurred in System.Windows.Browser.dll but was not handled in user code

    Additional information: [ScriptObject_TypeDoesNotExist]
    Arguments:XMLHttpRequest
    Debugging resource strings are unavailable. Often the key and arguments provide sufficient information to diagnose the problem. See http://go.microsoft.com/fwlink/?linkid=106663&Version=8.0.30226.2&File=System.Windows.Browser.dll&Key=ScriptObject_TypeDoesNotExist

    I can’t retrieve the data too, error on this line
    _xmlHttpRequest = HtmlPage.Window.CreateInstance(“XMLHttpRequest”);

    {System.ArgumentException: [ScriptObject_TypeDoesNotExist]
    Arguments:XMLHttpRequest
    Debugging resource strings are unavailable. Often the key and arguments provide sufficient information to diagnose the problem. See http://go.microsoft.com/fwlink/?linkid=106663&Version=8.0.30226.2&File=System.Windows.Browser.dll&Key=ScriptObject_TypeDoesNotExist
    Parameter name: typeName
    at System.Windows.Browser.HtmlWindow.CreateInstance(String typeName, Object[] args)
    at SL2Astoria.XMLHttpRequestWrapper.DoPost(Uri url, String httpVerb, String param)
    at SL2Astoria.XMLHttpRequestWrapper.DoPost(Uri url, String httpVerb)
    at SL2Astoria.Page.retrieveButton_Click(Object sender, RoutedEventArgs e)}

    Insert works.

  2. Hi,

    As I said in this post, updating need some changes. Retrieving, inserting and deleting is working.

    Please check the product id in products table before doing “delete” operation…

    In my sample, I used 18 (productid) for “delete” operation… but there is no product id 18 in products since I deleted this record when i was testing..

    so, please check the service url..

    For example:

    If you want to delete product id “17” then please change the service url as below.

    string serviceURL = “http://localhost:52976/SL2Astoria_Web/WebDataService.svc/Products(17)/”;

    then, it will work…

    another thing is that don’t close the browser so quick after clicking the button. you should give some time for processing..

    let me know the result.

  3. Hi,

    I had seen that the IDs was false, I had changed them but it didnt work. It’s not because I close the browser quick, VS2008 throw me an exception and debugging the solution I found the source of the error at this line :

    _xmlHttpRequest = HtmlPage.Window.CreateInstance(”XMLHttpRequest”);

    but I still don’t know why

  4. #1. Have you installed SL 2 SDK? (Please check in control panel) If you haven’t installed it yet, please install the SDK and try to run again..

    #2. Are you not able to create the XmlHttpRequest object? or which operations do you have problem? If you are not able to create XmlHttpRequest, you won’t be able to do any operations. Are you an administrator of your machine? I think it’s might be security issue.

  5. You said that inserting is working. so, you are able to create the XmlHttpRequest, isn’t it?

    So, Retrieve and Inserting are working for you? Only deleting? The error is very strange.. Please install SDK if you haven’t done yet. and please tell me which version of browsers are you using? Do you have permission to delete the record in SQL? Are you an administrator of your machine?

  6. Hi Michael,

    Thanks a lot for your help. The error looks like a security issue, but I’m administrator of my computer. I tested the solution on my notebook and It works… I hope I will find why it doesn’t work in my computer, my work station. I’m sorry it’s not really what I needed, I think I didnt explain very well. My goal is to use Entities in Silverlight like your sample in SL1.1

    MyEntities db = new MyEntities(UriOfTheDataService);
    var products = from p in db.Products
    select p;

    Working with a proxy class of my entities it’s really cool, but I guess we can’t do this without a WebClient library which supports that (maybe end of April).

    I thank you anyway for your job, it’s just not what I expected, world is not perfect!

    See you man

  7. Hi there

    i have bene attempting to floow this example but i am confused. i cannot seem to find the ado.net entity data model template at the start of the example. I am using vs2008 team edition and have installed astoria CTP sept. I am also using silverlight 2 beta 1 and blend 2.5 march.

    any ideas how to sort this out

    regards

    lee

  8. Hi desopedr,

    I know you want to use Astoria Client that is not currently available. but you are in hurry, right? So, you got two options 1) SL proxy + ASMX web service or WCF 2) SL XmlHttpRequest Wrapper + Astoria Web service.

    If you take option 1, you will need to change both SL project and Webservice or WCF project when you get to Astoria client.

    If you take option 2, you only need to change in SL project. you don’t need to do anything for Astoria web service that you created.

    So, I provide this solution for you. You can enjoy with XmlHttpRequest wrapper before you get Astoria client addon. When Astoria team release Client addon, you can change to SL prject. Your Astoria service will work without any change..

    Hello Lee,

    Please install the following installers.

    1. XML Editor QFE

    2. ADO.NET Entity Framework Beta 3

    3. ADO.Net Entity Framework Tools Dec 07 Community Technology Preview

    4. ASP.NET 3.5 Extensions Preview

  9. Hi there Michael

    Many many thanks for your prompt and very thoughtful reply. But you are right I cannot wait to get my teeth into this technology I personally think it a massive step forward and everyone who has contributed to it should be heartly congratulated.

    I will get on and install from the links you have provided.

    many thanks but I am sure I will have lots more questions in the learning process.

    best regards

    lee

  10. Hi Lee,

    You are welcomed! :)

    many thanks but I am sure I will have lots more questions in the learning process.

    Yeah. anytime.. buddy. :)

  11. Hi Michael,

    You are right, but change creating a data service it’s five/ten minutes. The biggest part of work is in the Silverlight side and with the WebDataClient library the code will be completly different.

    Maybe its better to wait end of April and to work on design, custom controls, animations until there.

    Thanks for help

  12. Hello Michael,

    I am Dhinesh Kumar Ganesan. I tried using your source code to try out the Silverlight beta 2 with VS 2008. I am stuck with the following error when i try running the application

    An exception of type ‘System.InvalidOperationException’ occurred in System.Windows.Browser.dll but was not handled in user code

    Additional information: Access is denied.

    Can you help me out to resolve this issue?

    Regards,

    Dhinesh Kumar

  13. Hello Dhinesh,

    Have you installed all required softwares (e.g. Entity Framework or SL runtime or etc)?

    Another thing is that you need to attach the SQL Database in your SQL server and you have to change the connectionstring.

    Can you please try to create one ADO.NET web service in your new project and see whether you are able to connect to SQL database or not?

  14. Hello Michael,

    Yes.Entity Framework or SL runtime or others –everything is installed.I have established connection with Server Explorer and connection is live.
    Yes I tried creating an ADO.NET Web Service and connect to SQL Database. It works. But the issue existing the XMLHttpWrapperClass in the DoPostMethod. I tried running your sample code with this but it throws an error in the Invoke method

    public static string DoPost(Uri url, string httpVerb, string param)
    {
    _xmlHttpRequest = HtmlPage.Window.CreateInstance(“XMLHttpRequest”);
    _xmlHttpRequest.Invoke(“open”, httpVerb, url,true);
    _xmlHttpRequest.Invoke(“setRequestHeader”, “Content-Type”, “application/json”);
    //_XMLHttpRequest.Invoke(“setRequestHeader”, “SOAPAction”, string.Concat(nspace, method));
    if (param == string.Empty) {
    _xmlHttpRequest.Invoke(“send”);
    }
    else {
    _xmlHttpRequest.Invoke(“send”, param);
    }

    ScriptObject dom = (ScriptObject)_xmlHttpRequest.GetProperty(“responseXML”);
    return (string)dom.GetProperty(“xml”);
    }

    Regards,

    Dhinesh Kumar

  15. Hi
    I have a ADO.Net service hosted on my PC and exposed using service bus. I have consumed this service in my .net web application and want to perform CRUD operation as above you mentioned.
    I tried the same code here, but I am getting error ” HtmlPage_NotEnabled ”
    And here is stack trace —
    ” at System.Windows.Browser.HtmlPage.VerifyThreadAndEnabled()\r\n at System.Windows.Browser.HtmlPage.get_Window()\r\n at GRSADOService_WebRole.XMLHttpRequestWrapper.DoPost(Uri url, String httpVerb, String param) in F:\\AZURE\\My Samples\\GRSADOService\\GRSADOService_WebRole\\XMLHttpRequestWrapper.cs:line 24″

    Can you please figure out the error ?

    Thanks,
    prashant