{"id":20940856,"url":"https://github.com/timhanewich/timhanewich.dataverse","last_synced_at":"2026-04-26T19:32:23.457Z","repository":{"id":52627657,"uuid":"295514703","full_name":"TimHanewich/TimHanewich.Dataverse","owner":"TimHanewich","description":"Helper library for transacting with Microsoft's Dataverse Service (formerly CDS/XRM)","archived":false,"fork":false,"pushed_at":"2023-09-18T16:47:27.000Z","size":167,"stargazers_count":2,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-12-26T08:34:59.916Z","etag":null,"topics":["cds","dataverse","dynamics","microsoft","xrm"],"latest_commit_sha":null,"homepage":"","language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/TimHanewich.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2020-09-14T19:14:08.000Z","updated_at":"2025-12-10T19:07:41.000Z","dependencies_parsed_at":"2024-11-18T23:22:40.644Z","dependency_job_id":null,"html_url":"https://github.com/TimHanewich/TimHanewich.Dataverse","commit_stats":null,"previous_names":["timhanewich/timhanewich.cds"],"tags_count":20,"template":false,"template_full_name":null,"purl":"pkg:github/TimHanewich/TimHanewich.Dataverse","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TimHanewich%2FTimHanewich.Dataverse","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TimHanewich%2FTimHanewich.Dataverse/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TimHanewich%2FTimHanewich.Dataverse/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TimHanewich%2FTimHanewich.Dataverse/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/TimHanewich","download_url":"https://codeload.github.com/TimHanewich/TimHanewich.Dataverse/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TimHanewich%2FTimHanewich.Dataverse/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32310804,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-26T19:15:34.056Z","status":"ssl_error","status_checked_at":"2026-04-26T19:15:15.467Z","response_time":129,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["cds","dataverse","dynamics","microsoft","xrm"],"created_at":"2024-11-18T23:12:07.762Z","updated_at":"2026-04-26T19:32:23.442Z","avatar_url":"https://github.com/TimHanewich.png","language":"C#","funding_links":[],"categories":[],"sub_categories":[],"readme":"![logo](https://i.imgur.com/ERemSkU.png)\n[**TimHanewich.Dataverse**](https://www.nuget.org/packages/TimHanewich.Dataverse/): A lightweight library for **easily** transacting with Microsoft's Dataverse service (formerly Common Data Service or \"XRM\"), the native data service of Microsoft's Power Platform and Dynamics 365 platform.  \n--------  \nMicrosoft provides [an excellent .NET SDK for interacting with the Dataverse API on NuGet](https://www.nuget.org/packages/Microsoft.PowerPlatform.Dataverse.Client). While this library offers extensive flexibility and well-defined capabilities, it can be a bit complex for most simple implementations. This library is designed to make both the authentication with Dataverse and consumption of Dataverse services easy.\n\nThis library supports:\n- Easily authenticate into Dataverse **without user interaction**.\n- Perform CRUD operations (**Create**, **Read**, **Update**, **Delete**) for any record.\n- Perform *advanced reads* that include **filtering**, **sorting**, **selection of specific fields**, etc.\n- **Access rich metadata** of any table or inter-table relationship.\n- *Humanize* any record of any table for use within a large language model (\"GPT\")\n\n### Install the package\nTo install the package in your .NET (C# or VB.NET) project, add the following package from NuGet:\n[TimHanewich.Dataverse](https://www.nuget.org/packages/TimHanewich.Dataverse/)\nRun this command in the .NET CLI:\n\n    dotnet add package TimHanewich.Dataverse\n\n### Authenticating with Dataverse\nThis class library supports authentication to the Dataverse web API. Use the `DataverseAuthenticator` class to authenticate.\n\n    DataverseAuthenticator auth = new DataverseAuthenticator();\n    auth.Username = \"\u003cyour username\u003e\";\n    auth.Password = \"\u003cyour password\u003e\";\n    auth.ClientId = Guid.Parse(\"51f81489-12ee-4a9e-aaae-a2591f45987d\");\n    auth.Resource = \"https://\u003cyour org\u003e.crm.dynamics.com/\";\n    await auth.GetAccessTokenAsync();\n\nAfter running the `GetAccessTokenAsync` method, your access token will be stored inside the DataverseAuthenticator object as the `AccessToken` property. Provide this `AccessToken` to the `DataverseService` constructor (see below) to start using the Dataverse web API.\n\n### Initializing the Dataverse Service\nPlace the following import statements at the top of your code file.\n\n    using TimHanewich.Dataverse;  \n    using Newtonsoft.Json;  \n    using Newtonsoft.Json.Linq;\n\nCreate a new Dataverse Service\n\n    DataverseService dv = new DataverseService(\"YourOrgName\", \"YourAccessToken\");\n\nIn the above example, replace \"YourOrgName\" with the organization name for your environment. For example, if your environment URL is https://org109a2adc0.crm.dynamics.com/, your org name is \"org109a2adc0\".  \n\nReplace \"YourAccessToken\" with the access token that you have received after authenticating through either the OAuth authentication flow or the above authentication using the `DataverseAuthenticator` class (recommended).\n\n### Creating a record\nWe will use the `CreateAsync` method of the DataverseService to create a new record. This method accepts two parameters:  \n- `setter` - the setter (schema) name of the entity. This can be found by going to https://\u003cyour_org_name\u003e.crm.dynamics.com/api/data/v9.0/ in an authenticated window.  \n- `json` - The JSON (`JObject`) content of the record that you are creating.  \n\nA complete example of initializing a Dataverse Service and creating a new account record:\n\n    DataverseService dv = new DataverseService(\"YourOrgName\", \"YourAccessToken\");\n    JObject jo = new JObject();\n    jo.Add(\"name\", \"Microsoft\"); //Specify name column of accounts table\n    await dv.CreateAsync(\"accounts\", jo).Wait();\n\n### Reading, Updating, and Deleting\nThe reading, updating, and deleting methods are very similar to the `CreateAsync` method that is detailed above. The only difference is that these three methods also have a parameter called `id` which serves as the unique identifier of the record that you'd like to transact on.  \nThis `id` parameter is the GUID value associated with the record that you can find in Dynamics 365 or the Power Platform Dataverse portal.\n\n## Working with Tables \u0026 Attributes\nThis package also provides the ability to read table and attribute structures. To leverage this capability import the resources by placing this statement at the top of your file:\n\n    using TimHanewich.Dataverse.Metadata;\n\n### Get a list of all records in the databse\nUse the `GetEntityMetadataSummariesAsync` method to receive and array of record summaries:\n\n    EntityMetadataSummary[] summaries = await service.GetEntityMetadataSummariesAsync();\n\nEach `EntityMetadataSummary` object contains the name of the record and \"URL Extension\" of the record that can be used to query records of this entity type.\n\n### Get metadata for a particular table\nUse the `GetEntityMetadataAsync` method to access metadata for a particular table.\n\n    EntityMetadata AccountsTableData = service.GetEntityMetadataAsync(\"account\").Result;\n\nThe `EntityMetadata` object provides details about all attributes (columns) in the table:\n\n    foreach (AttributeMetadata attribute in AccountsTableData.Attributes)\n    {\n        Console.WriteLine(attribute.DisplayName);\n        Console.WriteLine(attribute.SchemaName);\n        Console.WriteLine(attribute.LogicalName);\n        Console.WriteLine(attribute.Description);\n        Console.WriteLine(attribute.AttributeType.ToString());\n    }\n\n## Advanced Read Operation\nThis package also supports more complex read requests - for example, specifying certain columns to include, filtering based on column values, and requesting data from a related table.\n\n### Request a Single Record\nIf you know the unique ID of the record you would like data for, you can request a single record as such:\n```\nDataverseReadOperation read = new DataverseReadOperation();\nread.TableIdentifier = \"contacts\";\nread.RecordId = Guid.Parse(\"9b8b1f4d-da14-ec11-b6e6-000d3a99fcc1\");\nJArray QueryResults = await service.ReadAsync(read);\nConsole.WriteLine(\"Your one record:\");\nConsole.WriteLine(QueryResults[0].ToString());\n```\nIn the example above, the `service` object is an instance of the `DataverseService` class.\n\n### Specify Certain Columns\nTo save bandwidth and improve download times, you can also specify certain columns to include. Building from the code snippet above:\n```\nread.AddColumn(\"firstname\");\nread.AddColumn(\"lastname\");\n```\n*please note that if you do not specify a single column via the `AddColumn` method, all columns will be included by default.*\n\n### Add a Query Filter (or multiple!)\nYou can also add a filter to your query. For example, if you are trying to select all invoices with a total value over $1,000:\n```\nDataverseReadOperation read = new DataverseReadOperation();\nread.TableIdentifier = \"invoices\";\n\nDataverseReadFilter filter = new DataverseReadFilter();\nfilter.ColumnName = \"total\";\nfilter.Operator = ComparisonOperator.GreaterThan;\nfilter.SetValue(1000);\nread.AddFilter(filter);\n\nJArray results = await service.ExecuteDataverseReadOperationAsync(read);\n```\nIf you need to use multiple filter statements, you can also do this:\n```\nDataverseReadOperation read = new DataverseReadOperation();\nread.TableIdentifier = \"invoices\";\n\nDataverseReadFilter filter = new DataverseReadFilter();\nfilter.ColumnName = \"total\";\nfilter.Operator = ComparisonOperator.GreaterThan;\nfilter.SetValue(1000);\nread.AddFilter(filter);\n\nDataverseReadFilter filter2 = new DataverseReadFilter();\nfilter2.LogicalOperatorPrefix = LogicalOperator.And;\nfilter2.ColumnName = \"customer\";\nfilter2.SetValue(Guid.Parse(\"9b8b1f4d-da14-ec11-b6e6-000d3a99fcc1\"));\nread.AddFilter(filter2);\n\nJArray results = await service.ExecuteDataverseReadOperationAsync(read);\n```\nThe key above is to define the `LogicalOperatorPrefix` property of the second filter. This is the logical prefix (for example \"and\", \"or\") that will be added between this filter and the preceeding filter.\n\n### Request Data from a Related Record\nDataverse supports referrential table relationships via the **Lookup** data type. If you would like to include data from a related table, you can do so like this:\n```\nDataverseReadOperation read = new DataverseReadOperation();\nread.TableIdentifier = \"patients\";\n\nTableSelection related = new TableSelection();\nrelated.TableIdentifier = \"father\";\nread.Expand = related;\n```\nThe key above is to set the `Expand` property of the `DataverseReadOperation` to a `TableSelection` instance.  \nYou can also limit to only certain columns you would like from the related table:\n```\nDataverseReadOperation read = new DataverseReadOperation();\nread.TableIdentifier = \"patients\";\n\nTableSelection related = new TableSelection();\nrelated.TableIdentifier = \"father\";\nrelated.AddColumn(\"firstname\");\nrelated.AddColumn(\"lastname\");\nrelated.AddColumn(\"dateofbirth\");\nread.Expand = related;\n```\n\n## Humanization\nIn 2023 and beyond, using private data with **large language models** like the \"GPT\" series by OpenAI is a commonly desired implementation across industries. As part of the *prompt engineering* process, developers must incorporate private data into prompts to these large language models. The data must be in a *understandable*, *legible*, and *human-readable* format for the LLM to understand and use in its response. I call this process *humanization*.\n\nI've developed an algorithm to automatically perform this **humanization** process, **transforming the data from its raw form to a more human-readable form**. You can use the humanization capabilities of this package via the `HumanizeAsync` function of the `TimHanewich.Dataverse.Humanization` namespace:\n```\nDataverseService s = new DataverseService(\"\u003cYOUR DATAVERSE INSTANCE URL\u003e\", \"\u003cDATAVERSE ACCESS TOKEN\u003e\");\nJObject obj = await s.HumanizeAsync(\"cra0f_animal\", Guid.Parse(\"79f11b28-30c7-ed11-b597-000d3a8c2011\"));\nConsole.WriteLine(obj.ToString());\n```\nIn the code above, you must provide the `HummanizeAsync` method two parameters:  \n- The **logical name** of the table.\n- The **unqiue identifier** (GUID) of the record you'd like to hummanize.\n\nThe code above will turn a **raw** Dataverse record, that looks like this:\n```\n{\n  \"@odata.context\": \"https://org3d1a4090.crm.dynamics.com/api/data/v9.0/$metadata#cra0f_animals/$entity\",\n  \"@odata.etag\": \"W/\\\"4292472\\\"\",\n  \"cra0f_favoritespecies\": \"238080000,238080001,238080002\",\n  \"cra0f_dateofbirth\": \"2022-09-01T00:00:00Z\",\n  \"_owningbusinessunit_value\": \"5bd9dba0-c95c-ed11-9562-000d3a1df4a2\",\n  \"_cra0f_homepen_value\": \"95fc11dc-2fc7-ed11-b597-000d3a8c2011\",\n  \"cra0f_species\": 238080001,\n  \"statecode\": 0,\n  \"statuscode\": 1,\n  \"_cra0f_mother_value\": \"4f6a9a15-30c7-ed11-b597-000d3a8c2011\",\n  \"_createdby_value\": \"4de0dba0-c95c-ed11-9562-000d3a1df4a2\",\n  \"timezoneruleversionnumber\": 4,\n  \"_ownerid_value\": \"4de0dba0-c95c-ed11-9562-000d3a1df4a2\",\n  \"modifiedon\": \"2023-09-16T20:18:46Z\",\n  \"_owninguser_value\": \"4de0dba0-c95c-ed11-9562-000d3a1df4a2\",\n  \"_modifiedby_value\": \"4de0dba0-c95c-ed11-9562-000d3a1df4a2\",\n  \"versionnumber\": 4292472,\n  \"cra0f_name\": \"Phillip Piggy\",\n  \"createdon\": \"2023-03-20T15:01:57Z\",\n  \"cra0f_animalid\": \"79f11b28-30c7-ed11-b597-000d3a8c2011\",\n  \"overriddencreatedon\": null,\n  \"cra0f_wishesitwerea\": null,\n  \"importsequencenumber\": null,\n  \"_modifiedonbehalfby_value\": null,\n  \"utcconversiontimezonecode\": null,\n  \"_createdonbehalfby_value\": null,\n  \"_owningteam_value\": null\n}\n```\nInto *this*, a much more human-readable form that can easily be understood and leverage by a large language model in answering questions. As you can see below, the \"internal\" names of the columns are converted to their display names, the values are translated into their *labels*, and arbitrary values that are rather specific to Dataverse are trimmed from the payload:\n```\n{\n  \"Favorite Species\": \"Cow; Pig; Chicken\",\n  \"Date of Birth\": \"9/1/2022 12:00:00 AM\",\n  \"Species\": \"Pig\",\n  \"Modified On\": \"9/16/2023 8:18:46 PM\",\n  \"Name\": \"Phillip Piggy\",\n  \"Created On\": \"3/20/2023 3:01:57 PM\"\n}\n```\n\n### Hummanize with Relational Depth\nThe `HummanizeAsync` method also has a third (optional) parameter: `depth` (integer). This defines at what relational \"depth\" the hummanization should occur. For example, if one of the fields of the table you're hummanizing is a **lookup** field, specifing a depth \u003e 0 will also hummanize the record that is being pointed to and **append this related record** to the returned payload. For example, at a depth of **1**, this would be the response instead:\n```\n{\n  \"Favorite Species\": \"Cow; Pig; Chicken\",\n  \"Date of Birth\": \"9/1/2022 12:00:00 AM\",\n  \"Owning Business Unit\": {\n    \"Inheritance Mask\": 1023,\n    \"Modified On\": \"11/5/2022 5:20:58 AM\",\n    \"Created On\": \"11/5/2022 5:20:58 AM\",\n    \"Is Disabled\": false,\n    \"Name\": \"org3d1a4090\"\n  },\n  \"Home Pen\": {\n    \"Modified On\": \"3/20/2023 2:59:49 PM\",\n    \"Name\": \"Wayne Locks\",\n    \"Created On\": \"3/20/2023 2:59:49 PM\"\n  },\n  \"Species\": \"Pig\",\n  \"Mother\": {\n    \"Date of Birth\": \"2/16/2023 12:00:00 AM\",\n    \"Species\": \"Chicken\",\n    \"Modified On\": \"3/20/2023 3:01:26 PM\",\n    \"Name\": \"Caitlyn Chicky\",\n    \"Created On\": \"3/20/2023 3:01:26 PM\"\n  },\n  \"Created By\": {\n    \"Integration user mode\": false,\n    \"Main Phone\": \"425-555-0100\",\n    \"Access Mode\": \"Read-Write\",\n    \"First Name\": \"System\",\n    \"Restricted Access Mode\": false,\n    \"Incoming Email Delivery Method\": \"Server-Side Synchronization or Email Router\",\n    \"Primary Email\": \"admin@D365DemoTS909196.OnMicrosoft.com\",\n    \"Unique user identity id\": 3,\n    \"User Name\": \"admin@D365DemoTS909196.onmicrosoft.com\",\n    \"Created On\": \"11/5/2022 5:21:02 AM\",\n    \"Windows Live ID\": \"admin@D365DemoTS909196.onmicrosoft.com\",\n    \"Full Name\": \"System Administrator\",\n    \"License Type\": \"Enterprise\",\n    \"Modified On\": \"11/10/2022 2:50:51 PM\",\n    \"Azure State\": \"Exists\",\n    \"Default Filters Populated\": false,\n    \"Outgoing Email Delivery Method\": \"Server-Side Synchronization or Email Router\",\n    \"Address\": \"US\",\n    \"Primary Email Status\": \"Approved\",\n    \"Last Name\": \"Administrator\",\n    \"Mobile Phone\": \"425-555-0101\",\n    \"User Synced\": true,\n    \"User License Type\": 59,\n    \"Deleted State\": \"Not deleted\",\n    \"Default OneDrive for Business Folder Name\": \"CRM\",\n    \"Email Address O365 Admin Approval Status\": false,\n    \"Invitation Status\": \"Invitation Not Sent\",\n    \"Yomi Full Name\": \"System Administrator\",\n    \"Status\": false,\n    \"User PUID\": \"100320013C21A393\",\n    \"Country/Region\": \"US\",\n    \"User Licensed\": true\n  },\n  \"Owner\": {\n    \"Integration user mode\": false,\n    \"Main Phone\": \"425-555-0100\",\n    \"Access Mode\": \"Read-Write\",\n    \"First Name\": \"System\",\n    \"Restricted Access Mode\": false,\n    \"Incoming Email Delivery Method\": \"Server-Side Synchronization or Email Router\",\n    \"Primary Email\": \"admin@D365DemoTS909196.OnMicrosoft.com\",\n    \"Unique user identity id\": 3,\n    \"User Name\": \"admin@D365DemoTS909196.onmicrosoft.com\",\n    \"Created On\": \"11/5/2022 5:21:02 AM\",\n    \"Windows Live ID\": \"admin@D365DemoTS909196.onmicrosoft.com\",\n    \"Full Name\": \"System Administrator\",\n    \"License Type\": \"Enterprise\",\n    \"Modified On\": \"11/10/2022 2:50:51 PM\",\n    \"Azure State\": \"Exists\",\n    \"Default Filters Populated\": false,\n    \"Outgoing Email Delivery Method\": \"Server-Side Synchronization or Email Router\",\n    \"Address\": \"US\",\n    \"Primary Email Status\": \"Approved\",\n    \"Last Name\": \"Administrator\",\n    \"Mobile Phone\": \"425-555-0101\",\n    \"User Synced\": true,\n    \"User License Type\": 59,\n    \"Deleted State\": \"Not deleted\",\n    \"Default OneDrive for Business Folder Name\": \"CRM\",\n    \"Email Address O365 Admin Approval Status\": false,\n    \"Invitation Status\": \"Invitation Not Sent\",\n    \"Yomi Full Name\": \"System Administrator\",\n    \"Status\": false,\n    \"User PUID\": \"100320013C21A393\",\n    \"Country/Region\": \"US\",\n    \"User Licensed\": true\n  },\n  \"Modified On\": \"9/16/2023 8:18:46 PM\",\n  \"Owning User\": {\n    \"Integration user mode\": false,\n    \"Main Phone\": \"425-555-0100\",\n    \"Access Mode\": \"Read-Write\",\n    \"First Name\": \"System\",\n    \"Restricted Access Mode\": false,\n    \"Incoming Email Delivery Method\": \"Server-Side Synchronization or Email Router\",\n    \"Primary Email\": \"admin@D365DemoTS909196.OnMicrosoft.com\",\n    \"Unique user identity id\": 3,\n    \"User Name\": \"admin@D365DemoTS909196.onmicrosoft.com\",\n    \"Created On\": \"11/5/2022 5:21:02 AM\",\n    \"Windows Live ID\": \"admin@D365DemoTS909196.onmicrosoft.com\",\n    \"Full Name\": \"System Administrator\",\n    \"License Type\": \"Enterprise\",\n    \"Modified On\": \"11/10/2022 2:50:51 PM\",\n    \"Azure State\": \"Exists\",\n    \"Default Filters Populated\": false,\n    \"Outgoing Email Delivery Method\": \"Server-Side Synchronization or Email Router\",\n    \"Address\": \"US\",\n    \"Primary Email Status\": \"Approved\",\n    \"Last Name\": \"Administrator\",\n    \"Mobile Phone\": \"425-555-0101\",\n    \"User Synced\": true,\n    \"User License Type\": 59,\n    \"Deleted State\": \"Not deleted\",\n    \"Default OneDrive for Business Folder Name\": \"CRM\",\n    \"Email Address O365 Admin Approval Status\": false,\n    \"Invitation Status\": \"Invitation Not Sent\",\n    \"Yomi Full Name\": \"System Administrator\",\n    \"Status\": false,\n    \"User PUID\": \"100320013C21A393\",\n    \"Country/Region\": \"US\",\n    \"User Licensed\": true\n  },\n  \"Modified By\": {\n    \"Integration user mode\": false,\n    \"Main Phone\": \"425-555-0100\",\n    \"Access Mode\": \"Read-Write\",\n    \"First Name\": \"System\",\n    \"Restricted Access Mode\": false,\n    \"Incoming Email Delivery Method\": \"Server-Side Synchronization or Email Router\",\n    \"Primary Email\": \"admin@D365DemoTS909196.OnMicrosoft.com\",\n    \"Unique user identity id\": 3,\n    \"User Name\": \"admin@D365DemoTS909196.onmicrosoft.com\",\n    \"Created On\": \"11/5/2022 5:21:02 AM\",\n    \"Windows Live ID\": \"admin@D365DemoTS909196.onmicrosoft.com\",\n    \"Full Name\": \"System Administrator\",\n    \"License Type\": \"Enterprise\",\n    \"Modified On\": \"11/10/2022 2:50:51 PM\",\n    \"Azure State\": \"Exists\",\n    \"Default Filters Populated\": false,\n    \"Outgoing Email Delivery Method\": \"Server-Side Synchronization or Email Router\",\n    \"Address\": \"US\",\n    \"Primary Email Status\": \"Approved\",\n    \"Last Name\": \"Administrator\",\n    \"Mobile Phone\": \"425-555-0101\",\n    \"User Synced\": true,\n    \"User License Type\": 59,\n    \"Deleted State\": \"Not deleted\",\n    \"Default OneDrive for Business Folder Name\": \"CRM\",\n    \"Email Address O365 Admin Approval Status\": false,\n    \"Invitation Status\": \"Invitation Not Sent\",\n    \"Yomi Full Name\": \"System Administrator\",\n    \"Status\": false,\n    \"User PUID\": \"100320013C21A393\",\n    \"Country/Region\": \"US\",\n    \"User Licensed\": true\n  },\n  \"Name\": \"Phillip Piggy\",\n  \"Created On\": \"3/20/2023 3:01:57 PM\"\n}\n```\n\nYou can see in the code above, the **hummanized** version of several *related records* are also included in their appropriate properties. When extending to a depth of **2**, the related records of the core record's related records will also be included. As such, the `HummanizationAsync` method is **recursive**, using the product of itself to extend to related records.\n\n### How does Hummanization Work?\nUsing metadata from Dataverse for your record of interest and related tables, the `HummanizeAsync` method makes several modifications to the standard (raw) Dataverse record payload:\n\n1. Removes properties with null values.\n2. Remove unneeded fields (fields that are primary internal to Dataverse): OData-specific fields, state code, status code, time zone rule conversation, version number, unique identifier, etc.\n3. Convert property **logical names** to their **display name** alternatives.\n4. Translate any choice fields from their integer-value representation to their label (text) equivalent.\n5. Format dates (i.e. `2023-03-20T15:01:57Z` to `3/20/2023 3:01:57 PM`).\n6. Apply same procedure as above to related records and append to core record (if `depth` \u003e 0).\n\nYou can review the code of the `HummanizeAsync` method [here](./src/Huminization/HumanizationToolkit.cs).","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftimhanewich%2Ftimhanewich.dataverse","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftimhanewich%2Ftimhanewich.dataverse","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftimhanewich%2Ftimhanewich.dataverse/lists"}