Служба данных WCF не может обработать UPDATE для записей фидов - PullRequest
0 голосов
/ 08 июля 2010

Я и мой приятель пытаемся начать работу с WCF Data Services, поэтому позвольте мне сначала описать, что мы уже сделали:

  1. Мы создали довольно простой WCFСлужба данных с источником данных, который реализует интерфейс IUpdatable и предоставляет некоторые данные через некоторые открытые атрибуты IQueryable <> (код прикреплен внизу).Используя Visual Studio 2010, сначала мы запустили наш сервис в IIS 7, но из-за ошибок, которые мы не смогли выяснить, мы решили запустить его с помощью Cassini (веб-сервер Webdev).

  2. Мы написали клиента на C # для использования сервиса.Клиент работает, как предполагается, со всеми различными операциями с данными (создание, чтение, обновление и удаление).Все идет нормально!При размещении службы на веб-сервере IIS 7 нам приходилось использовать туннелирование POST для выполнения обновлений и удалений, но теперь оно работает как положено.

  3. Наша проблема возникает, когда мы пытаемся использоватьобслуживание с нашими клиентами Java (Restlet) и Ruby (ruby_odata): мы не можем обновить данные с этими клиентами (мы получаем ответ «500 Internal Server Error» и «Method Not Allowed» от сервера).Мы использовали два довольно простых урока [a, b], которые кажутся довольно простыми для создания наших клиентов.Поэтому мы считаем, что наши проблемы заключаются в нашем обслуживании.

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

Оба эти клиента перечислены как 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 голосов
/ 08 июля 2010

На этот же вопрос ответили здесь: http://social.msdn.microsoft.com/Forums/en-US/adodotnetdataservices/thread/31d3f2f0-3dd2-479f-8b44-45f59eef0c53/

Проблема в том, что PUT в конечном итоге вызовет ResetResource, который, как ожидается, вернет действительный экземпляр ресурса, а не ноль.

...