WCF Data Service BeginSaveChanges not saving changes in Silverlight app
- by Enigmativity
I'm having a hell of a time getting WCF Data Services to work within Silverlight. I'm using the VS2010 RC.
I've struggled with the cross domain issue requiring the use of clientaccesspolicy.xml & crossdomain.xml files in the web server root folder, but I just couldn't get this to work. I've resorted to putting both the Silverlight Web App & the WCF Data Service in the same project to get past this issue, but any advice here would be good.
But now that I can actually see my data coming from the database and being displayed in a data grid within Silverlight I thought my troubles were over - but no. I can edit the data and the in-memory entity is changing, but when I call BeginSaveChanges (with the appropriate async EndSaveChangescall) I get no errors, but no data updates in the database.
Here's my WCF Data Services code:
public class MyDataService : DataService<MyEntities>
{
public static void InitializeService(DataServiceConfiguration config)
{
config.SetEntitySetAccessRule("*", EntitySetRights.All);
config.SetServiceOperationAccessRule("*", ServiceOperationRights.All);
config.DataServiceBehavior.MaxProtocolVersion = DataServiceProtocolVersion.V2;
}
protected override void OnStartProcessingRequest(ProcessRequestArgs args)
{
base.OnStartProcessingRequest(args);
HttpContext context = HttpContext.Current;
HttpCachePolicy c = HttpContext.Current.Response.Cache;
c.SetCacheability(HttpCacheability.ServerAndPrivate);
c.SetExpires(HttpContext.Current.Timestamp.AddSeconds(60));
c.VaryByHeaders["Accept"] = true;
c.VaryByHeaders["Accept-Charset"] = true;
c.VaryByHeaders["Accept-Encoding"] = true;
c.VaryByParams["*"] = true;
}
}
I've pinched the OnStartProcessingRequest code from Scott Hanselman's article Creating an OData API for StackOverflow including XML and JSON in 30 minutes.
Here's my code from my Silverlight app:
private MyEntities _wcfDataServicesEntities;
private CollectionViewSource _customersViewSource;
private ObservableCollection<Customer> _customers;
private void UserControl_Loaded(object sender, RoutedEventArgs e)
{
if (!System.ComponentModel.DesignerProperties.GetIsInDesignMode(this))
{
_wcfDataServicesEntities = new MyEntities(new Uri("http://localhost:7156/MyDataService.svc/"));
_customersViewSource = this.Resources["customersViewSource"] as CollectionViewSource;
DataServiceQuery<Customer> query = _wcfDataServicesEntities.Customer;
query.BeginExecute(result =>
{
_customers = new ObservableCollection<Customer>();
Array.ForEach(query.EndExecute(result).ToArray(), _customers.Add);
Dispatcher.BeginInvoke(() =>
{
_customersViewSource.Source = _customers;
});
}, null);
}
}
private void button1_Click(object sender, RoutedEventArgs e)
{
_wcfDataServicesEntities.BeginSaveChanges(r =>
{
var response = _wcfDataServicesEntities.EndSaveChanges(r);
string[] results = new[]
{
response.BatchStatusCode.ToString(),
response.IsBatchResponse.ToString()
};
_customers[0].FinAssistCompanyName = String.Join("|", results);
}, null);
}
The response string I get back data binds to my grid OK and shows "-1|False".
My intent is to get a proof-of-concept working here and then do the appropriate separation of concerns to turn this into a simple line-of-business app.
I've spent hours and hours on this. I'm being driven insane. Any ideas how to get this working?