{"id":671,"date":"2008-06-11T12:54:11","date_gmt":"2008-06-11T11:54:11","guid":{"rendered":"http:\/\/www.itwriting.com\/blog\/?page_id=671"},"modified":"2022-01-02T18:17:02","modified_gmt":"2022-01-02T18:17:02","slug":"simple-crud-with-silverlight-20","status":"publish","type":"page","link":"https:\/\/www.itwriting.com\/blog\/articles\/simple-crud-with-silverlight-20","title":{"rendered":"Simple CRUD with Silverlight 2.0"},"content":{"rendered":"<p>I spent a couple of hours putting together a simple CRUD (Create, Retrieve, Update, Delete) application with Silverlight 2.0 Beta 2.<\/p>\n<p><img decoding=\"async\" src=\"http:\/\/www.itwriting.com\/images\/simplecrud.gif\" alt=\"\"><\/p>\n<p>Most of the examples I\u2019ve seen use LINQ to SQL; that\u2019s fine, but I wanted to do something without that intermediate layer.<\/p>\n<p>I created a new database called SilverlightGuestBook with a single table, GuestBook. It has three columns: ID (identity), Name and Comment.<\/p>\n<p>Next I started a new Silverlight application in Visual Studio. How am I going to create and update the data? Send SQL strings back from Silverlight? Ummm &#8230; no, that\u2019s a security hole the size of Microsoft\u2019s offer for Yahoo. I figured it would be best to send a custom object back and forth.<\/p>\n<p>In the web application, I created a GuestItem class that has properties for ID, Comment and CommentName. Next, I added a DataManager class with three functions:<\/p>\n<pre>public static List&lt;GuestItem&gt; GetGuestEntries()\npublic static bool DeleteGuestItem(int ID)\npublic static bool SaveGuestItem(GuestItem gi)<\/pre>\n<p>I wrote code for these that just uses SqlConnection,SqlCommand and SQlDataReader, using parameters rather than embedding user-provided values in the SQL. When SaveGuestItem sees an ID of less than zero, it creates a new row; otherwise, it updates the row based on the ID. I do some minimal validation, such as checking for empty values.<\/p>\n<p>Then I added a Silverlight-enabled WCF Service called GuestBook. This simply wraps the three functions in DataManager. In other words, the web service serializes my GuestItem objects and sends them to the client.<\/p>\n<h3>Assembling the client<\/h3>\n<p>My Silverlight form has a grid layout with a DataGrid and several buttons and controls. I set a ServiceReference to the GuestBook web service. Here\u2019s the code to populate the grid:<\/p>\n<pre>void refreshGuestList()\n {\nvar ws = new GuestBookService.GuestBookClient();\nws.GetGuestItemsCompleted +=\n   new EventHandler&lt;GuestBookService.GetGuestItemsCompletedEventArgs&gt;(ws_GetGuestItemsCompleted);\nws.GetGuestItemsAsync();\n&nbsp;} \n\nvoid ws_GetGuestItemsCompleted(object sender, GuestBookService.GetGuestItemsCompletedEventArgs e)\n&nbsp;{\n this.GuestList.ItemsSource = e.Result;\n&nbsp;}<\/pre>\n<p>The app relies on auto-generated columns, which is why CommentName is used as a header; this kind of thing can easily be fixed.<\/p>\n<p>I handle the DataGrid\u2019s SelectionChanged event to populate the form. This is really simple: just cast the DataGrid\u2019s SelectedItem property to a GuestItem, and then write these properties to the form. Clicking the Add new entry button clears the form for a new entry. I have an mCurrentID variable that keeps track of the ID identifying the currently displayed entry.<\/p>\n<p>Incidentally, I spotted what looks like a bug in the DataGrid. The SelectedIndex property is meant to give you the index of the selected row. In my tests it always seems to return -1, even then SelectedItem is not null.<\/p>\n<p>The Save button creates a new GuestItem based on the values in the form, calls the SaveGuestItem method, then refreshes the grid. The Delete button calls DeleteGuestItem and then refreshes the grid.<\/p>\n<h3>A few comments<\/h3>\n<p>The app works nicely. It is not using any special features of WCF and would work just as well with old-style ASP.NET web services as far as I can see.<\/p>\n<p>I realise that a real guest book would not allow any user to edit any entry. Authentication is the big missing piece. However, this should be straightforward to implement on the server. Perhaps a logged-in admin user could edit any entry; while anonymous users could only add entries. I could also hide or disable disallowed features.<\/p>\n<p>What about when Mr Hacker enters strange values in the fields \u2013 say, XAML with script? Interesting question, and I\u2019d like to know what Microsoft advises here. I guess the data should be sanitized either when saved, or when returned. That said, I wasn\u2019t able to get any content to misbehave with a few quick tests.<\/p>\n<p>As you can see, I actually wrote my own very simple object-relational mapper to create this application. This is a fair amount of work for a complex application, which suggests that using something like LINQ to SQL or Entity Framework does make sense. On the other hand, there are advantages in hand-rolling the code. It may be more efficient, and it can be easier to debug.<\/p>\n<p>The bottom line is that putting together a basic CRUD application is not difficult, which is as it should be.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>I spent a couple of hours putting together a simple CRUD (Create, Retrieve, Update, Delete) application with Silverlight 2.0 Beta 2. Most of the examples I\u2019ve seen use LINQ to SQL; that\u2019s fine, but I wanted to do something without that intermediate layer. I created a new database called SilverlightGuestBook with a single table, GuestBook. &hellip; <a href=\"https:\/\/www.itwriting.com\/blog\/articles\/simple-crud-with-silverlight-20\" class=\"more-link\">Continue reading <span class=\"screen-reader-text\">Simple CRUD with Silverlight 2.0<\/span> <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"parent":2036,"menu_order":150,"comment_status":"closed","ping_status":"closed","template":"","meta":{"footnotes":""},"class_list":["post-671","page","type-page","status-publish","hentry"],"_links":{"self":[{"href":"https:\/\/www.itwriting.com\/blog\/wp-json\/wp\/v2\/pages\/671","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.itwriting.com\/blog\/wp-json\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/www.itwriting.com\/blog\/wp-json\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/www.itwriting.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.itwriting.com\/blog\/wp-json\/wp\/v2\/comments?post=671"}],"version-history":[{"count":1,"href":"https:\/\/www.itwriting.com\/blog\/wp-json\/wp\/v2\/pages\/671\/revisions"}],"predecessor-version":[{"id":11945,"href":"https:\/\/www.itwriting.com\/blog\/wp-json\/wp\/v2\/pages\/671\/revisions\/11945"}],"up":[{"embeddable":true,"href":"https:\/\/www.itwriting.com\/blog\/wp-json\/wp\/v2\/pages\/2036"}],"wp:attachment":[{"href":"https:\/\/www.itwriting.com\/blog\/wp-json\/wp\/v2\/media?parent=671"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}