WCF数据服务无法处理订阅源条目的UPDATE

时间:2010-07-08 10:06:32

标签: c# wcf rest service odata

我和我的一些好友正在尝试使用WCF数据服务,所以让我先描述一下到目前为止我们做了什么:

  1. 我们创建了一个相当简单的WCF数据服务,其中包含一个实现IUpdatable接口的数据源,并通过一些公共IQueryable<>来公开一些数据。属性(代码附在底部)。使用Visual Studio 2010,我们首先在IIS 7中运行我们的服务,但是由于我们无法弄清楚的错误,我们决定使用Cassini(Webdev webserver)来运行它。

  2. 我们在C#中编写了一个客户端来使用该服务。客户端与所有不同的数据操作(创建,读取,更新和删除)一起工作。到现在为止还挺好!在IIS 7网络服务器上托管服务时,我们必须使用POST隧道进行更新和删除工作,但现在它正在按预期工作。

  3. 当我们尝试使用Java(Restlet)和Ruby(ruby_odata)客户端使用服务时出现问题:我们无法使用这些客户端更新数据(我们收到“500 Internal Server Error”和“方法不允许“来自服务器的回复”。我们使用了两个相当简单的教程[a,b],它们看起来都非常简单,可以创建我们的客户。因此,我们认为我们的问题在于我们的服务。

  4. 一个。 ruby_odata:http://rdoc.info/projects/visoft/ruby_odata
    湾restlet:http://wiki.restlet.org/docs_2.0/13-restlet/28-restlet/287-restlet/288-restlet.html

    这两个客户端都列为OData SDK(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都使用HTTP PUT进行更新。这可能只是我们的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;
            }*/
        }
    }
    

1 个答案:

答案 0 :(得分:0)

同样的问题在这里回答:http://social.msdn.microsoft.com/Forums/en-US/adodotnetdataservices/thread/31d3f2f0-3dd2-479f-8b44-45f59eef0c53/

问题是PUT最终会调用ResetResource,它应该返回一个有效的资源实例而不是null。