Building a CRUD Web API with Dataverse Entities in ASP.NET Web API: A Beginner's Guide

Building a CRUD Web API with Dataverse Entities in ASP.NET Web API: A Beginner's Guide

Introduction

In modern application development, integrating with robust data platforms is essential for scalability and flexibility. Microsoft Dataverse (formerly known as Common Data Service) provides a secure and cloud-based storage option for your data, acting as the underlying data platform for Microsoft Power Platform and Dynamics 365 applications.

In this tutorial, we'll guide you through creating a CRUD (Create, Read, Update, Delete) Web API using a Dataverse entity in ASP.NET Web API. This step-by-step guide is designed for beginner programmers, offering detailed explanations and code samples.

Prerequisites

Before you begin, ensure you have the following:

  • Visual Studio 2022 (Community Edition is sufficient)
  • .NET 6 SDK or later
  • An active Dataverse environment (available through a Power Apps trial)
  • Basic knowledge of C# and .NET
  • Azure Active Directory (Azure AD) access (for app registration)
  • Microsoft.PowerPlatform.Dataverse.Client NuGet package

Table of Contents

  1. Setting Up the Development Environment
  2. Creating a Dataverse Entity
  3. Creating the ASP.NET Web API Project
  4. Connecting to Dataverse from the Web API
  5. Implementing CRUD Operations
  6. Testing the API
  7. Conclusion

1. Setting Up the Development Environment

Install Visual Studio 2022

  • Download and install Visual Studio 2022 Community Edition from the official website.
  • During installation, select the following workloads:
    • ASP.NET and web development
    • .NET desktop development

Install .NET 6 SDK

Set Up a Dataverse Environment


2. Creating a Dataverse Entity

Access Dataverse in Power Apps

  • Navigate to Dataverse > Tables in the left-hand menu.

Create a New Table (Entity)

  1. Click on + New table.

  2. Configure the new table:

    • Display Name: Student
    • Plural Display Name: Students
    • Primary Column: Student Name
    • Click Create.

Add Columns to the Table

Add the following columns to the Student table:

  1. Age

    • Data type: Number (Whole Number)
  2. Email

    • Data type: Text
  3. Enrollment Date

    • Data type: Date and Time (Date Only)

Save the table after adding all columns.


3. Creating the ASP.NET Web API Project

Create a New Project

  1. Open Visual Studio 2022.
  2. Click on Create a new project.
  3. Select ASP.NET Core Web API.
  4. Click Next.

Configure the Project

  1. Project Name: DataverseWebApi
  2. Location: Choose your preferred directory.
  3. Click Next.

Set Additional Information

  1. Framework: .NET 8.0 (Long-term support)
  2. Authentication Type: None
  3. Enable OpenAPI support: Checked (for Swagger UI)
  4. Click Create.

4. Connecting to Dataverse from the Web API

To interact with Dataverse, we'll use the Microsoft.PowerPlatform.Dataverse.Client NuGet package.

Install the NuGet Package

  1. Right-click on the project in Solution Explorer.
  2. Select Manage NuGet Packages.
  3. Go to the Browse tab, search for Microsoft.PowerPlatform.Dataverse.Client.
  4. Install the latest stable version.

Register an Application in Azure AD

  1. Go to the Azure Portal.

  2. Navigate to Azure Active Directory > App registrations.

  3. Click New registration.

    • Name: DataverseWebApiApp
    • Supported account types: Accounts in this organizational directory only
    • Redirect URI: https://localhost
    • Click Register.
  4. Note down the Application (client) ID.

  5. In Certificates & secrets, create a new client secret. Note it down.

Add Connection String to appsettings.json

Open appsettings.json and add your Dataverse connection string:


{
  "ConnectionStrings": {
    "Dataverse": "AuthType=ClientSecret;Url=https://yourorg.crm.dynamics.com;ClientId=your_client_id;ClientSecret=your_client_secret;LoginPrompt=Auto"
  }
}
  • Replace https://yourorg.crm.dynamics.com with your Dataverse organization URL.
  • Replace your_client_id and your_client_secret with the values from Azure AD.

Security Note: For production, use secure methods like Azure Key Vault to store secrets.


5. Implementing CRUD Operations

Create a Model for Student

Create a Models folder. Add a new class Student.cs:


using System;

namespace DataverseWebApi.Models
{
    public class Student
    {
        public Guid Id { get; set; }
        public string StudentName { get; set; }
        public int Age { get; set; }
        public string Email { get; set; }
        public DateTime EnrollmentDate { get; set; }
    }
}

Create a Service to Interact with Dataverse

Create a Services folder. Add a new class DataverseService.cs:


using Microsoft.PowerPlatform.Dataverse.Client;
using Microsoft.Xrm.Sdk;
using Microsoft.Xrm.Sdk.Query;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using DataverseWebApi.Models;
using Microsoft.Extensions.Configuration;

namespace DataverseWebApi.Services
{
    public class DataverseService
    {
        private readonly ServiceClient _serviceClient;

        public DataverseService(IConfiguration configuration)
        {
            var connectionString = configuration.GetConnectionString("Dataverse");
            _serviceClient = new ServiceClient(connectionString);
        }

        public async Task<Guid> CreateStudentAsync(Student student)
        {
            var entity = new Entity("student"); // Replace with your entity logical name
            entity["studentname"] = student.StudentName;
            entity["age"] = student.Age;
            entity["email"] = student.Email;
            entity["enrollmentdate"] = student.EnrollmentDate;

            return await Task.Run(() => _serviceClient.Create(entity));
        }

        public async Task<Student> GetStudentAsync(Guid id)
        {
            var columns = new ColumnSet("studentname", "age", "email", "enrollmentdate");
            var entity = await Task.Run(() => _serviceClient.Retrieve("student", id, columns));

            if (entity == null) return null;

            return new Student
            {
                Id = entity.Id,
                StudentName = entity.GetAttributeValue<string>("studentname"),
                Age = entity.GetAttributeValue<int>("age"),
                Email = entity.GetAttributeValue<string>("email"),
                EnrollmentDate = entity.GetAttributeValue<DateTime>("enrollmentdate")
            };
        }

        public async Task UpdateStudentAsync(Student student)
        {
            var entity = new Entity("student", student.Id);
            entity["studentname"] = student.StudentName;
            entity["age"] = student.Age;
            entity["email"] = student.Email;
            entity["enrollmentdate"] = student.EnrollmentDate;

            await Task.Run(() => _serviceClient.Update(entity));
        }

        public async Task DeleteStudentAsync(Guid id)
        {
            await Task.Run(() => _serviceClient.Delete("student", id));
        }

        public async Task<List<Student>> GetStudentsAsync()
        {
            var query = new QueryExpression("student")
            {
                ColumnSet = new ColumnSet("studentname", "age", "email", "enrollmentdate")
            };

            var entities = await Task.Run(() => _serviceClient.RetrieveMultiple(query));

            var students = new List<Student>();

            foreach (var entity in entities.Entities)
            {
                students.Add(new Student
                {
                    Id = entity.Id,
                    StudentName = entity.GetAttributeValue<string>("studentname"),
                    Age = entity.GetAttributeValue<int>("age"),
                    Email = entity.GetAttributeValue<string>("email"),
                    EnrollmentDate = entity.GetAttributeValue<DateTime>("enrollmentdate")
                });
            }

            return students;
        }
    }
}

Explanation:

  • Entity Logical Names: Replace "student", "studentname", etc., with your actual entity logical names from Dataverse.
  • ServiceClient: Manages the connection to Dataverse.

Register the Service in Dependency Injection

In Program.cs, add:


builder.Services.AddSingleton<DataverseService>();

Create the StudentsController

Create a new controller StudentsController.cs in the Controllers folder:


using DataverseWebApi.Models;
using DataverseWebApi.Services;
using Microsoft.AspNetCore.Mvc;
using System;
using System.Collections.Generic;
using System.Threading.Tasks;

namespace DataverseWebApi.Controllers
{
    [Route("api/[controller]")]
    [ApiController]
    public class StudentsController : ControllerBase
    {
        private readonly DataverseService _dataverseService;

        public StudentsController(DataverseService dataverseService)
        {
            _dataverseService = dataverseService;
        }

        // GET: api/Students
        [HttpGet]
        public async Task<ActionResult<IEnumerable<Student>>> GetStudents()
        {
            var students = await _dataverseService.GetStudentsAsync();
            return Ok(students);
        }

        // GET: api/Students/{id}
        [HttpGet("{id}")]
        public async Task<ActionResult<Student>> GetStudent(Guid id)
        {
            var student = await _dataverseService.GetStudentAsync(id);

            if (student == null)
            {
                return NotFound();
            }

            return Ok(student);
        }

        // POST: api/Students
        [HttpPost]
        public async Task<ActionResult<Student>> CreateStudent(Student student)
        {
            var id = await _dataverseService.CreateStudentAsync(student);
            student.Id = id;

            return CreatedAtAction(nameof(GetStudent), new { id = student.Id }, student);
        }

        // PUT: api/Students/{id}
        [HttpPut("{id}")]
        public async Task<IActionResult> UpdateStudent(Guid id, Student student)
        {
            if (id != student.Id)
            {
                return BadRequest();
            }

            await _dataverseService.UpdateStudentAsync(student);

            return NoContent();
        }

        // DELETE: api/Students/{id}
        [HttpDelete("{id}")]
        public async Task<IActionResult> DeleteStudent(Guid id)
        {
            await _dataverseService.DeleteStudentAsync(id);

            return NoContent();
        }
    }
}

Explanation:

  • Each action method corresponds to a CRUD operation.
  • Dependency Injection: The controller uses DataverseService injected via constructor.

6. Testing the API

Run the Application

Press F5 in Visual Studio to run the application. The Swagger UI should open automatically.

Using Swagger UI

Create a New Student

  1. Expand POST /api/Students.

  2. Click Try it out.

  3. Enter the following JSON in the Request body:

    
    {
      "studentName": "Alice Smith",
      "age": 22,
      "email": "alice.smith@example.com",
      "enrollmentDate": "2023-09-01"
    }
    
  4. Click Execute.

  5. You should receive a 201 Created response with the student details.

Retrieve All Students

  1. Expand GET /api/Students.
  2. Click Try it out and then Execute.
  3. The response should list all students in Dataverse.

Update a Student

  1. Copy the Id of the student you want to update.
  2. Expand PUT /api/Students/{id}.
  3. Click Try it out.
  4. Enter the Id in the id parameter.
  5. Modify the JSON in the Request body as needed.
  6. Click Execute.

Delete a Student

  1. Expand DELETE /api/Students/{id}.
  2. Click Try it out.
  3. Enter the Id of the student to delete.
  4. Click Execute.

Verify in Dataverse

  • Return to the Power Apps portal.
  • Open the Students table to see the changes reflected.

Conclusion

You've successfully built a CRUD Web API using a Dataverse entity in ASP.NET Web API! This API can be extended or integrated into other applications, providing a powerful way to manage data stored in Dataverse.

Key Takeaways

  • Dataverse Integration: Leveraging Dataverse allows for scalable and secure data management.
  • ServiceClient Usage: The Microsoft.PowerPlatform.Dataverse.Client simplifies interactions with Dataverse.
  • ASP.NET Web API: Building APIs with ASP.NET Core is efficient and aligns with modern web development practices.

Next Steps

  • Security Enhancements: Implement secure storage for connection strings and secrets (e.g., using Azure Key Vault).
  • Error Handling: Add robust error handling and logging mechanisms.
  • Authentication: Secure your API endpoints with authentication and authorization.

Additional Resources


Looking to optimize your software skills? Visit askpedromartins.com for expert advice and solutions tailored to your development needs.

Back to blog
  • ChatGPT Uncovered Podcast

    ChatGPT Uncovered Podcast

    Pedro Martins

    ChatGPT Uncovered Podcast ChatGPT Uncovered Podcast Exploring the Frontiers of AI Conversational Models Episode 1: Understanding ChatGPT Published on: May 15, 2023 Your browser does not support the audio element....

    ChatGPT Uncovered Podcast

    Pedro Martins

    ChatGPT Uncovered Podcast ChatGPT Uncovered Podcast Exploring the Frontiers of AI Conversational Models Episode 1: Understanding ChatGPT Published on: May 15, 2023 Your browser does not support the audio element....

  • Power Apps In-Depth Podcast

    Power Apps In-Depth Podcast

    Pedro Martins

    Power Apps In-Depth Podcast Power Apps In-Depth Podcast Exploring the Capabilities of Microsoft Power Apps Episode 1: Introduction to Power Apps Published on: April 20, 2023 Your browser does not...

    Power Apps In-Depth Podcast

    Pedro Martins

    Power Apps In-Depth Podcast Power Apps In-Depth Podcast Exploring the Capabilities of Microsoft Power Apps Episode 1: Introduction to Power Apps Published on: April 20, 2023 Your browser does not...

  • Exploring Power Pages Podcast

    Exploring Power Pages Podcast

    Pedro Martins

    Exploring Power Pages Podcast Exploring Power Pages Podcast Delving into the World of Microsoft Power Pages Episode 1: Getting Started with Power Pages Published on: March 10, 2023 Your browser...

    Exploring Power Pages Podcast

    Pedro Martins

    Exploring Power Pages Podcast Exploring Power Pages Podcast Delving into the World of Microsoft Power Pages Episode 1: Getting Started with Power Pages Published on: March 10, 2023 Your browser...

1 of 3