simple-odata-client / Simple.OData.Client

MIT License
329 stars 196 forks source link

Suffix Rules needs an update - Pluralize entities ending with "s" #692

Open mangzee opened 4 years ago

mangzee commented 4 years ago

In one of my recent projects, I have been stuck with an issue where I'm unable to retrieve bind/link an entity using Simple.Odata.Client

The payload from InsertEntryAsync is as below,

{ "@odata.type": "#Microsoft.Dynamics.CRM.bookableresourcebooking", "duration": 60, "starttime": "2019-12-08T00:00:00+05:30", "endtime": "2019-12-09T00:00:00+05:30", "bookingtype": 1, "name": "MJTEST02", "BookingStatus@odata.bind": "https://xyz.crm11.dynamics.com/api/data/v9.1/bookingstatus(fb123229-f1fd-e911-a811-000d3a86d6ea)", "Resource@odata.bind": "https://xyz.crm11.dynamics.com/api/data/v9.1/bookableresources(7cb5669d-b815-ea11-a811-000d3a86d6ce)", "msdyn_ResourceRequirement@odata.bind": "https://xyz.crm11.dynamics.com/api/data/v9.1/msdyn_resourcerequirements(215b5b14-1b17-ea11-a811-000d3a86d545)" }

If you notice above for "BookingStatus@odata.bind" , the entity name is bookingstatus and hence the collection name should have been "bookingstatuses" which unfortunately it is not :(

Had a quick look into the file https://github.com/simple-odata-client/Simple.OData.Client/blob/master/src/Simple.OData.Client.Core/SimplePluralizer.cs and it doesn't seem that it can convert the name to a proper collection.

static readonly string[] _suffixRulesStringTable = { "ch", "ches", "sh", "shes", "ss", "sses", "ay", "ays", "ey", "eys", "iy", "iys", "oy", "oys", "uy", "uys", "y", "ies", "ao", "aos", "eo", "eos", "io", "ios", "oo", "oos", "uo", "uos", "o", "oes", "cis", "ces", "sis", "ses", "xis", "xes", "louse", "lice", "mouse", "mice", "zoon", "zoa", "man", "men", "deer", "deer", "fish", "fish", "sheep", "sheep", "itis", "itis", "ois", "ois", "pox", "pox", "ox", "oxes", "foot", "feet", "goose", "geese", "tooth", "teeth", "alf", "alves", "elf", "elves", "olf", "olves", "arf", "arves", "leaf", "leaves", "nife", "nives", "life", "lives", "wife", "wives", };

It would be great either to handle the above OR provide a way to mention the collection name as a class attribute. [Collection(Name ="bookingstatuses")]

anandvn commented 4 years ago

This is a workaround I've come up with for my projects:

Internal Collection Attribute Class:


[AttributeUsage(AttributeTargets.Class)]
internal class CollectionAttribute : Attribute
    {
        public string Name { get; set; }
    }

internal static class CollectionNameHelper
    {
        public static string GetCollectionName(this Type T)
        {
            var attrs = T.GetCustomAttributes(typeof(CollectionAttribute), false);
            if ((attrs != null) && attrs.Count() > 0)
                return ((CollectionAttribute)attrs.First()).Name;
            return string.Empty;
        }
    }

POCO Classes:


    [Collection(Name = "VendorsV2")]
    internal class VendorV2
    {
        public string dataAreaId { get; set; }
        public string VendorOrganizationName { get; set; }
        public string VendorAccountNumber { get; set; }
    }

Usage:

                var suppliers = await Client
                        .For<VendorV2>(typeof(VendorV2).GetCollectionName())
                        .FindEntriesAsync()
mangzee commented 4 years ago

@anandvn Thank you so much, I did end up creating a similar custom attribute :)