moi et certains de mes amis tentent de démarrer avec WCF Data Services, alors laissez-moi d'abord décrire ce que nous avons fait jusqu'à présent:WCF Data Service ne peut pas gérer Mise à jour sur les entrées d'alimentation
Nous ont créé un service de données WCF assez simple avec une source de données qui implémente l'interface IUpdatable et expose certaines données via certains attributs publics IQueryable <> (le code est attaché en bas). À l'aide de Visual Studio 2010, nous avons d'abord exécuté notre service dans IIS 7, mais en raison d'erreurs que nous n'avons pas pu résoudre, nous avons décidé de l'utiliser avec Cassini (Webdev webserver).
Nous avons écrit un client en C# pour consommer le service. Le client fonctionne comme supposé avec toutes les différentes opérations de données (créer, lire, mettre à jour et supprimer). Jusqu'ici tout va bien! Lors de l'hébergement du service sur le serveur Web IIS 7, nous avons dû utiliser le tunneling POST pour effectuer des mises à jour et supprimer des travaux, mais maintenant cela fonctionne comme prévu. Notre problème survient lorsque nous essayons de consommer le service avec nos clients Java (Restlet) et Ruby (ruby_odata): nous ne pouvons pas mettre à jour les données avec ces clients (nous obtenons une erreur "500 Internal Server Error" et "Method"). Non autorisé "réponse du serveur). Nous avons utilisé deux tutoriels assez simples [a, b] qui semblent assez simples pour créer nos clients. Nous croyons donc que nos problèmes sont à notre service.
a. ruby_odata: http: //rdoc.info/projects/visoft/ruby_odata
b. restlet: http: //wiki.restlet.org/docs_2.0/13-restlet/28-restlet/287-restlet/288-restlet.html
Ces deux clients sont répertoriés en tant que OData SDK (http://www.odata.org/developers/odata-sdk) et doivent fonctionner correctement pour consommer le flux OData. Une chose que nous avons remarquée lors de la surveillance des requêtes HTTP, est que le client C# utilise le verbe HTTP MERGE pour les mises à jour (regardez ici pour plus d'informations: http://blogs.msdn.com/b/astoriateam/archive/ 2008/05/20/merge-vs-replace-semantics-for-update-operations.aspx), tandis que Java et Ruby utilisent HTTP PUT pour les mises à jour. Serait-ce la raison pour laquelle seul notre client C# fonctionne? Que pouvons-nous faire pour activer les mises à jour PUT?
Nous venons de commencer avec .NET, et apprécierions si cela pouvait être pris en considération lorsque vous répondez
using System;
using System.Collections.Generic;
using System.Data.Services;
using System.Linq;
using System.Data.Services.Providers;
using System.Reflection;
using System.ServiceModel.Web;
using System.Data.Services.Common;
namespace WCFDataServiceApp
{
public class Product
{
public int ID { get; set; }
public string Name { get; set; }
public string Color { get; set; }
public Category ProductCategory { get; set; }
}
public class Category
{
public int ID { get; set; }
public string Name { get; set; }
}
public class AWData : IUpdatable
{
static List<Category> categories;
static List<Product> products;
static AWData()
{
categories = new List<Category>() {
new Category { ID = 1, Name = "Bikes" },
new Category { ID = 2, Name = "Parts" },
new Category { ID = 3, Name = "Wheels"},
};
products = new List<Product>() {
new Product { ID = 1, Name = "Red Bike", Color = "Red", ProductCategory = categories[0] },
new Product { ID = 2, Name = "Blue Bike", Color = "Blue", ProductCategory = categories[0] },
new Product { ID = 3, Name = "Green Bike", Color = "Green", ProductCategory = categories[0] },
new Product { ID = 4, Name = "Yellow Bike", Color = "Yellow", ProductCategory = categories[0] },
new Product { ID = 5, Name = "Pink Bike", Color = "Pink", ProductCategory = categories[0] },
new Product { ID = 6, Name = "Black Bike", Color = "Black", ProductCategory = categories[0] }
};
}
public IQueryable<Category> Categories
{
get { return categories.AsQueryable(); }
}
public IQueryable<Product> Products
{
get { return products.AsQueryable(); }
}
void IUpdatable.AddReferenceToCollection(object targetResource, string propertyName, object resourceToBeAdded)
{
System.Diagnostics.Debug.WriteLine("No support for AddReferenceToCollection(object targetResource, string propertyName, object resourceToBeAdded)");
}
void IUpdatable.ClearChanges()
{
System.Diagnostics.Debug.WriteLine("ClearChanges()");
}
public object CreateResource(string containerName, string fullTypeName)
{
System.Diagnostics.Debug.WriteLine("CreateResource(string containerName, string fullTypeName)");
Type t = Type.GetType(fullTypeName);
// Check if resource exists
if (t != null)
{
object resource = Activator.CreateInstance(t);
if (containerName.Equals("Categories"))
{
categories.Add((Category)resource);
}
else if (containerName.Equals("Products"))
{
products.Add((Product)resource);
}
return resource;
}
// Current resource does not exist
return new Exception("Could not create a resource of type " + containerName);
}
void IUpdatable.DeleteResource(object targetResource)
{
// 1. Check object type
if (targetResource.GetType().IsInstanceOfType(new Category()))
{
System.Diagnostics.Debug.WriteLine("Category deleted!");
categories.Remove((Category)targetResource);
}
else if (targetResource.GetType().IsInstanceOfType(new Product()))
{
System.Diagnostics.Debug.WriteLine("Product deleted!");
products.Remove((Product)targetResource);
}
}
object IUpdatable.GetResource(IQueryable query, string fullTypeName)
{
System.Diagnostics.Debug.WriteLine("GetResource(IQueryable query, string fullTypeName)");
object obj = null;
foreach (object o in query)
{
obj = o;
}
return obj;
}
object IUpdatable.GetValue(object targetResource, string propertyName)
{
System.Diagnostics.Debug.WriteLine("GetValue(object targetResource, string propertyName)");
return null;
}
void IUpdatable.RemoveReferenceFromCollection(object targetResource, string propertyName, object resourceToBeRemoved)
{
System.Diagnostics.Debug.WriteLine("RemoveReferenceFromCollection(object targetResource, string propertyName, object resourceToBeRemoved)");
}
object IUpdatable.ResetResource(object resource)
{
System.Diagnostics.Debug.WriteLine("ResetResource(object resource)");
return null;
}
object IUpdatable.ResolveResource(object resource)
{
return resource;
}
void IUpdatable.SaveChanges()
{
System.Diagnostics.Debug.WriteLine("SaveChanges()");
}
void IUpdatable.SetReference(object targetResource, string propertyName, object propertyValue)
{
System.Diagnostics.Debug.WriteLine("SetReference(object targetResource, string propertyName, object propertyValue)");
}
void IUpdatable.SetValue(object targetResource, string propertyName, object propertyValue)
{
PropertyInfo pi = targetResource.GetType().GetProperty(propertyName);
if (pi == null)
throw new Exception("Can't find property");
pi.SetValue(targetResource, propertyValue, null);
System.Diagnostics.Debug.WriteLine("Object " + targetResource + " updated value " + propertyName + " to " + propertyValue);
}
public void SetConcurrencyValues(object resourceCookie, bool? checkForEquality, IEnumerable<KeyValuePair<string, object>> concurrencyValues)
{
System.Diagnostics.Debug.WriteLine("SetConcurrencyValues(object resourceCookie, bool? checkForEquality, IEnumerable<KeyValuePair<string, object>> concurrencyValues) was called");
throw new Exception("SetConcurrencyValues(object resourceCookie, bool? checkForEquality, IEnumerable<KeyValuePair<string, object>> concurrencyValues) not implemented");
}
}
public class aw : DataService<AWData> //, IServiceProvider
{
// This method is called only once to initialize service-wide policies.
public static void InitializeService(DataServiceConfiguration config)
{
config.SetEntitySetAccessRule("*", EntitySetRights.All);
//config.DataServiceBehavior.MaxProtocolVersion = DataServiceProtocolVersion.V2;
}
/*
public object GetService(Type serviceType)
{
System.Diagnostics.Debug.WriteLine(serviceType.ToString());
return this;
}*/
}
}