私と私の仲間の何人かはWCFデータサービスを始めようとしているので、最初に私たちがこれまでに行ったことを説明しましょう。
IUpdatableインターフェイスを実装し、いくつかのパブリックIQueryable <>属性を介して一部のデータを公開するデータソースを使用して、非常に単純なWCFデータサービスを作成しました(コードは下部に添付されています)。Visual Studio 2010を使用して、最初はIIS 7でサービスを実行しましたが、エラーが原因で理解できなかったため、代わりにCassini(Webdev Webサーバー)で実行することにしました。
サービスを利用するためにC#でクライアントを作成しました。クライアントは、すべての異なるデータ操作(作成、読み取り、更新、および削除)で想定どおりに機能します。ここまでは順調ですね!IIS 7 Webサーバーでサービスをホストする場合、POSTトンネリングを使用して更新と削除を機能させる必要がありましたが、現在は意図したとおりに機能しています。
Java(Restlet)およびRuby(ruby_odata)クライアントでサービスを利用しようとすると、問題が発生します。これらのクライアントでデータを更新できません(「500内部サーバーエラー」および「メソッドが許可されていません」という応答が返されます)。サーバー) 。クライアントを作成するために、2つの非常に単純なチュートリアル[a、b]を使用しましたが、どちらも非常に簡単に思えます。したがって、私たちの問題は私たちのサービスにあると信じています。
a。ruby_odata:http://rdoc.info/projects/visoft/ruby_odatab
。レストレット:http://wiki.restlet.org/docs_2.0/13-restlet/28-restlet/287-restlet/288-restlet.html
これらのクライアントは両方ともODataSDK(http://www.odata.org/developers/odata-sdk)としてリストされており、ODataフィードを利用するには正常に機能しているはずです。
HTTPリクエストを監視しているときに気付いたのは、C#クライアントが更新にHTTP MERGE動詞を使用していることです(詳細については、http://blogs.msdn.com/b/astoriateam/archive/2008/05/を参照してください)。 20 / merge-vs-replace-semantics-for-update-operations.aspx)、JavaとRubyの両方が更新にHTTPPUTを使用します。これが、C#クライアントのみが機能する理由でしょうか?PUTの更新を有効にするために何ができますか?
.NETを始めたばかりですが、答えるときにそれを考慮に入れていただければ幸いです。
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;
}*/
}
}