Dataverse.Http.Connector.Core 1.0.4

dotnet add package Dataverse.Http.Connector.Core --version 1.0.4
                    
NuGet\Install-Package Dataverse.Http.Connector.Core -Version 1.0.4
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Dataverse.Http.Connector.Core" Version="1.0.4" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Dataverse.Http.Connector.Core" Version="1.0.4" />
                    
Directory.Packages.props
<PackageReference Include="Dataverse.Http.Connector.Core" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Dataverse.Http.Connector.Core --version 1.0.4
                    
#r "nuget: Dataverse.Http.Connector.Core, 1.0.4"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package Dataverse.Http.Connector.Core@1.0.4
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Dataverse.Http.Connector.Core&version=1.0.4
                    
Install as a Cake Addin
#tool nuget:?package=Dataverse.Http.Connector.Core&version=1.0.4
                    
Install as a Cake Tool

Dataverse HTTP Connector Core

Dataverse HTTP Connector Core library was created to help to the developers to create useful application connected to a Dataverse (or usually called Dynamics) environment in less time.

The package currently works using an Application User connection because this one has more request capacity. You only need to create a new App Registration resource in Microsoft Azure, grant it permissions to connect to Dynamics and then register the Application User in Admin Power Platform portal.

New features

Feature Description Examples
Renamed field for column Any reference to Field was modified to Column. FieldAttributeColumnAttribute FieldTypeColumnType
New attributes Now you can configure columns definitions using new classes. Text Number DecimalNumber Lookup DateTimeOf OptionSet BoolOptionSet UniqueIdentifier
Read only attributes If you want to retrieve a column value but you don't want this be set in a create or update operations, you can set as readonly. SchemaName, LogicalName, ReadOnly [Text("FullName", "fullname", true)]

Getting Started

Let's see an example about how you can implement this library in an ASP.NET Core application.

Configure connection

First of all make sure that you configure your connection inside one of the .json files. The configuration can be like the following.

"Dataverse": {
  "tenantId": "{ tenant unique identifier }",
  "clientId": "{ client unique identifier }",
  "clientSecret": "{ secret }",
  "resource": "{ dynamics url environment }",
  "connectionName": "{ custom identifier name }"
}

Each one of these values must be unique because you can configure multiple environments if you want.

"Dataverses": [
  {
    "tenantId": "{ tenant unique identifier }",
    "clientId": "{ client unique identifier }",
    "clientSecret": "{ secret }",
    "resource": "{ dynamics url environment }",
    "connectionName": "Org. #1"
  },
  {
    "tenantId": "{ tenant unique identifier }",
    "clientId": "{ client unique identifier }",
    "clientSecret": "{ secret }",
    "resource": "{ dynamics url environment }",
    "connectionName": "Org. #2"
  }
]

Create your entity class

You also will need to create your custom classes that will be used to connect to Dataverse and use require context.

using Dataverse.Http.Connector.Core.Domains.Annotations;

namespace Dataverse.Web.API.Models
{
    [Entity("crmit_employee", "crmit_employees")]
    public class Employees
    {
        [UniqueIdentifier("crmit_EmployeeId", "crmit_employeeid")]
        public Guid Id { get; set; }

        [Text("crmit_Name", "crmit_name")]
        public string? Name { get; set; }

        [Text("crmit_EmployeeNumber", "crmit_employeenumber")]
        public string? EmployeeNumber { get; set; }

        [DateTimeOf("CreatedOn", "createdon")]
        public DateTime CreatedOn { get; set; }

        [DateTimeOf("ModifiedOn", "modifiedon")]
        public DateTime ModifiedOn { get; set; }

        [OptionSet("statuscode", "statuscode")]
        public int StatusCode { get; set; }

        [OptionSet("statecode", "statecode")]
        public int StateCode { get; set; }

        [BoolOptionSet("crmit_IsDeleted", "crmit_isdeleted")]
        public bool IsDeleted { get; set; }

        [Lookup("OwnerId", "ownerid", "systemusers")]
        public Guid OwnerId { get; set; }
    }
}

As you can see in the previous example, you define your class and use Entity class to set Entity logical name and Entity collection logical name attributes.

To configure entity properties you can use one of the following annotations classes.

  • Text
  • Number
  • DecimalNumber
  • Lookup
  • DateTimeOf
  • OptionSet
  • BoolOptionSet
  • UniqueIdentifier

Configure Dataverse service

Once that you have ready your configuration inside .json file and are created the entity classes you will need to call an extension method as you can see in the following code.

builder.Services.AddDataverseContext<DataverseContext>(config =>
{
    config.AddConnections(builder.Configuration.GetSection("Dataverses").Get<List<DataverseConnection>>()); // The default connection will be the first one.
    config.SetDefaultConnection(
        builder.Configuration.GetSection("Dataverse").Get<DataverseConnection>()
    ); // You can set a default connection. If the connection does not exist, will add it.
    config.AddEntitiesFromAssembly(typeof(Employees).Assembly); // You can add multiples entities definitions using assembly reference.
});

As you can see, with the new update you can use AddEntitiesFromAssembly method instead AddEntityDefinition<TEntity>() function.

The last you need to do is use this library.

Dataverse service example

In your controller you need to use IDataverseContext service.

using Microsoft.AspNetCore.Mvc;
using Dataverse.Web.API.Models;
using Dataverse.Http.Connector.Core.Persistence;
using Dataverse.Http.Connector.Core.Extensions.Utilities;

namespace Dataverse.Web.API.Controllers
{
    [Route("api/[controller]")]
    [ApiController]
    public class EmployeesController : ControllerBase
    {
        private readonly IDataverseContext _dataverse;

        public EmployeesController(IDataverseContext dataverse)
            => _dataverse = dataverse;

        [HttpGet]
        public async Task<IActionResult> GetEmployee()
        {
            var employees = await _dataverse.Set<Employees>().ToListAsync();
            return Ok(employees);
        }

        [HttpGet("paged")]
        public async Task<IActionResult> GetPagedEmployee([FromQuery] int page, [FromQuery] int pageSize)
        {
            var pagedEmployees = await _dataverse.Set<Employees>().ToPagedListAsync(page, pageSize);
            return Ok(pagedEmployees);
        }

        [HttpGet("{id}")]
        public async Task<IActionResult> GetEmployee([FromRoute] Guid id)
        {
            var employee = await _dataverse.Set<Employees>()
                .FilterAnd(conditions => 
                {
                    conditions.Equal(x => x.Id, id);
                })
                .FirstOrDefaultAsync();

            if (employee is null)
                return NotFound();
            return Ok(employee);
        }

        [HttpPost]
        public async Task<IActionResult> CreateEmployee([FromBody] Employees model)
        {
            await _dataverse.Set<Employees>().AddAsync(model);

            if (model.Id == Guid.Empty)
                return BadRequest();

            return Ok(model);
        }

        [HttpPut("{id}")]
        public async Task<IActionResult> UpdateEmployee([FromRoute] Guid id, [FromBody] Employees model)
        {
            var employee = await _dataverse.Set<Employees>().FilterAnd(conditions => conditions.Equal(x => x.Id, id)).FirstOrDefaultAsync();

            if (employee is null)
                return NotFound();

            model.Id = id;

            await _dataverse.Set<Employees>().UpdateAsync(model);
            return Ok(model);
        }

        [HttpDelete("{id}")]
        public async Task<IActionResult> DeleteEmployee([FromRoute] Guid id)
        {
            var employee = await _dataverse.Set<Employees>().FilterAnd(conditions => conditions.Equal(x => x.Id, id)).FirstOrDefaultAsync();

            if (employee is null)
                return NotFound();

            await _dataverse.Set<Employees>().DeleteAsync(employee);
            return Ok();
        }
    }
}

To add different conditions when you use a filter for a query, it's needed to add the package using Dataverse.Http.Connector.Core.Extensions.Utilities to have access to different conditions like:

  • Equal
  • NotEqual
  • Between
  • NotBetween
  • And much more...

This is a simple example about the implementation of this library. If any error during the request execution ocurred, automatically will throw an exception.

To get more information about the exception you can access to the data named Content of the exception generated by this library.

try 
{

}
catch(Exception ex)
{
    var content = ex.Data["Content"];
}

If you configured many connection, you can change between those using a code as the following.

public async Task<IActionResult> GetEmployee(Guid id)
{
    var employee = await _dataverse.Set<Employees>().FilterAnd(conditions => conditions.Equal(x => x.Id, id)).FirstOrDefaultAsync();
    if(employee is null) 
    {
        _dataverse.SetEnvironment($"Name, unique identifier or dataverse connection instance");
        employee = await _dataverse.Set<Employees>().FilterAnd(conditions => conditions.Equal(x => x.Id, id)).FirstOrDefaultAsync();
    }
    return Ok(employee);
}

Now you have all what you need to start to use Dataverse HTTP Connector Core.

Considerations

This library currently does not support the link-entity join for a query request, but in future versions will be added this functionality.

If you like this library, don't forget that you can support it if you want. This is an open source project, and you are free if you want to help to improve it.

Repository

Authors

Product Compatible and additional computed target framework versions.
.NET net7.0 is compatible.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 was computed.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 was computed.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 was computed.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.0.4 275 8/1/2023
1.0.3 232 6/15/2023
1.0.2 236 6/14/2023
1.0.1 231 6/10/2023
1.0.0 240 6/9/2023

Renamed field for columns to configure an Entity for Dataverse connection.

Created New annotations for centity columns's configurations.

Added new configuration in Column attribute to define if a column is read only (create and update operations will be skipped for this column).

Fixed build for FetchXml for Greater Than, Greater Equal, Less Than, Less Equal condition types.