Giter VIP home page Giter VIP logo

wcfds-toolkit's People

Contributors

oising avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

wcfds-toolkit's Issues

HttpContext Items "ODataQueryOperation.Current" added twice

When querying with the "$inlinecount=allpages" option, ODataQueryProvider attempts to add the same key twice to the HttpContext.Current.Items collection.

ODataQueryProvider.cs, line 112 should be changed from:
HttpContext.Current.Items.Add("ODataQueryOperation.Current", operation);
to:
HttpContext.Current.Items["ODataQueryOperation.Current"] = operation;

RemoveReferenceFromCollection not implemented! And better support for the 'propertyName' argument!

Hi again. I notice that following limitations / issues in the current version of the Toolkit:

(1) AddReferenceToCollection do not store anywhere the 'propertyName' argument, and for my use-case this argument is mandatory, or else, I cannot know exactly in which sub-property exactly of an entity should be added the new entity. E.g. POST http://server/OData.svc/Users('foo')/$links/Products
If the Users entity have the same Type for /Products and for /SpecialProducts is impossible to know where to add the new entity in which collection.
My change was the following:

public void AddReferenceToCollection(object targetResource, string propertyName, object resourceToBeAdded)
{
this._currentOperation = "AddReferenceToCollection";
this._currentOperationProperty = propertyName;
this._currentEntity = targetResource;
this._currentRelatedEntity = resourceToBeAdded;
}

    [...]

    public void SaveChanges()
    {
        if (_currentOperation == null)
            return;

        var repository = RepositoryFor(_currentEntity.GetType().FullName);

        if (repository == null)
            return;

        if (_currentOperation == "CreateResource" || _currentOperation == "ModifyResource")
            ExecuteMethodIfExists(repository, "Save", _currentEntity);

        if (_currentOperation == "DeleteResource")
            ExecuteMethodIfExists(repository, "Remove", _currentEntity);

        if (_currentOperation == "AddReferenceToCollection")
            ExecuteMethodIfExists(repository, string.Format("Create{0}Relation", _currentOperationProperty), _currentEntity, _currentRelatedEntity);

        if (_currentOperation == "RemoveReferenceFromCollection")
            ExecuteMethodIfExists(repository, string.Format("Remove{0}Relation", _currentOperationProperty), _currentEntity, _currentRelatedEntity);
    }

(2) RemoveReferenceFromCollection is not implemented. This do not work for the following example:

DELETE http://server/OData.svc/Users('foo')/$links/Products('xpto')

I adapted the Add implementation to this Remove method, and this was the result:

public void RemoveReferenceFromCollection(object targetResource, string propertyName, object resourceToBeRemoved)
{
this._currentOperation = "RemoveReferenceFromCollection";
this._currentOperationProperty = propertyName;
this._currentEntity = targetResource;
this._currentRelatedEntity = resourceToBeRemoved;
}

Problem with $expand when the Model have loops between object types

Hi, first of all, thank you a lot for this great toolkit.

Right now, i'm having a trouble using $expand property from the OData protocol when using an expand in a Object which have other property object which have a List<> of the first Object (loop of object references).

My model is something like:

public class Content
{
public string Id { get; set; }
public string Title { get; set; }
public Channel Channel { get; set; }
}

public class Channel
{
    public string Id { get; set; }
    public string Name { get; set; }
    public IList<Content> Contents { get; set; }
}

And i invoke something like: "http://localhost/OData.svc/Contents?$expand=Channel&$select=Id,Channel"

I already identified the problem in the "Microsoft.Data.Services.Toolkit.QueryModel.TypeExtensions" class, and made the following changes.

public static IDictionary GetPropertyDetails(this IEnumerable properties, Type type) { var projectedProperties = new Dictionary(); var projectedTypes = new List() { type }; Action, Func> processProperties = null; processProperties = delegate(IEnumerable propertyList, Func accessor) { if (accessor == null) accessor = o => o;
            foreach (var property in propertyList)
            {
                var local = property;
                if (property.PropertyType.IsValueType || property.PropertyType == typeof(string))
                {
                    var propertyDetails = new PropertyDetails
                                              {
                                                  PropertyInfo = local,
                                                  PropertySetter = (target, value) => local.SetValue(accessor(target), Convert.ChangeType(value, local.PropertyType.TypeOrElementType()), null)
                                              };

                    projectedProperties.Add(local.GetUnderlyingColumnName(), propertyDetails);
                }
                else if (property.PropertyType.IsArray)
                {
                    var propertyDetails = new PropertyDetails
                    {
                        PropertyInfo = local,
                        PropertySetter = (target, value) => local.SetValue(accessor(target), value, null)
                    };

                    projectedProperties.Add(local.GetUnderlyingColumnName(), propertyDetails);
                }
                else
                {
                    if (!projectedTypes.Contains(local.PropertyType))
                    {
                        projectedTypes.Add(local.PropertyType);
                        processProperties(local.PropertyType.GetProperties(BindingFlags.Public | BindingFlags.Instance), o => local.GetValue(accessor(o), null));
                    }
                }
            }
        };

        processProperties(properties, null);
        return projectedProperties;
    }

Basically I added a list of types already iterated to avoid a loop in recursion of the processProperties(...) method! That way, it works just fine. Otherwise, it occurs an Exception in the Dictionary repeated key, and if you do an if before to check if it contains that key, occurs a StackOverflow because of the loop recursion problem.

Do you confirm that this is a bug, or am I doing something wrong?

Problem with Batch support

Hi, i'm having also another issue with the Batch feature of OData.

This feature let us make more than one OData request in a single HTTP POST request.

http://www.odata.org/documentation/odata-v2-documentation/batch-processing/

Basically, when I use the batch functionality with only one request in the POST body, it works. But when I use more than one request in the POST body, it occurs one exception of duplicate insert in the dictionary "HttpContext.Current.Items.Add("ODataQueryOperation.Current", operation)" that is present in class "Microsoft.Data.Services.Toolkit.QueryModel.ODataQueryProvider".

To solve this, I simple removed that line, because I noticed that is not used by nothing else.

Best regards,
Carlos Torrão

ContextParameters should include more information

I would like to determine when a client has specified an "$expand" operation on my endpoint so that I can decided whether or not to load the data. By default, the ODataQueryOperation.Current.ContextParameters does not include querystring items that start with a "$".

Line 53 of ODataQueryProvider.cs should be changed from:

var queryStringDictionary = queryString.AllKeys.Where(p => !p.StartsWith("$")).ToDictionary(k => k, p => queryString[p]);

to

var queryStringDictionary = queryString.AllKeys.ToDictionary(k => k, p => queryString[p]);

so that we can inspect the context to determine whether the $expand operation was requested.

In fact, it would be nice to include $expand-specific properties in ODataQueryOperation itself, similar to how ProjectedProperties works.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.