A cool OData hack in LightSwitch

Introduction

Warning: this post is nerd-only. :)

We’ll try to add a record directly over the Odata service, even without making a service reference !

Our Setting

We simply start with an empty LightSwitch application in which we add:

  • an entity type “Customer” with 2 fields: LastName and FirstName
  • A completely empty screen (start with a new data screen and do not relate it to an entity type)

How?

using System;
using System.Linq;
using System.IO;
using System.IO.IsolatedStorage;
using System.Collections.Generic;
using Microsoft.LightSwitch;
using Microsoft.LightSwitch.Framework.Client;
using Microsoft.LightSwitch.Presentation;
using Microsoft.LightSwitch.Presentation.Extensions;
using LightSwitchApplication.Implementation;
using System.Data.Services.Client;
namespace LightSwitchApplication
{
    public partial class ODataUpdate
    {
        [global::System.Data.Services.Common.EntitySetAttribute("Customers")]
        [global::System.Data.Services.Common.DataServiceKeyAttribute("Id")]
        public class MyCustomer
        {
            public int Id { get; set; }
            public string LastName { get; set; }
            public string FirstName { get; set; }
            public byte[] RowVersion { get; set; }

        }

        partial void AddCustomer_Execute()
        {
            MyCustomer c = new MyCustomer();
            c.FirstName = "paul";
            c.LastName = "van bladel";

            Microsoft.LightSwitch.Threading.Dispatchers.Main.BeginInvoke(() =>
            {
                Uri uri = new Uri(System.Windows.Application.Current.Host.Source, "../ApplicationData.svc");
                DataServiceContext _appService = new DataServiceContext(uri);
                _appService.AddObject("Customers", c);
                _appService.BeginSaveChanges(SaveChangesOptions.Batch, (IAsyncResult ac) =>
                {
                     _appService = ac.AsyncState as DataServiceContext;
                     DataServiceResponse response = _appService.EndSaveChanges(ac);
                },
                _appService);
            });

        }
    }
}

I needed to introduce a separate MyCustomer class and decorate this with the EntitySet and DataServiceKey attributes. When I try to do the save with the Customer type instead I get, for unknown reasons, and error: “This operation requires the entity to be of an Entity Type, either mark its key properties, or attribute the class with DataServiceEntityAttribute”. Strange, because I would suspect the build-in LightSwitch type Customer having these attributes.  The MyCustomer type needs to have as well the RowVersion field.

As you can see, it works with the good old BeginExecute and EndExecute async pattern.

Could this be useful?

For your daily LightSwitch work, the answer is: by and large no !

But… imagine you want to do inter-application communications without making explicit service references towards eachother… Just update the Uri variable and you are up speed :)