Create an ASP.NET Core Web API CRUD Service
- 6 minutes to read
This help topic describes how to implement a controller in an existing ASP.NET Core Web API project.
#Access a UnitOfWork Object
XPO supports ASP.NET Core Dependency Injection, which means that you can add a UnitOfWork object as a constructor argument.
using Microsoft.AspNetCore.Mvc;
using DevExpress.Xpo;
// ...
public class CustomersController : ControllerBase {
private UnitOfWork uow;
public CustomersController(UnitOfWork uow) {
this.uow = uow;
}
}
To make this work, call the AddXpoDefaultUnitOfWork method from the application’s startup code. Refer to the Add Required Services section in this document for details.
#Implement Get Methods
To implement Get
methods, use LINQ to XPO and Projection Operations to create a collection of anonymous objects:
using Microsoft.AspNetCore.Mvc;
using DevExpress.Xpo;
// ...
readonly UnitOfWork UnitOfWork;
[HttpGet]
public ActionResult Get() {
try {
var data = UnitOfWork.Query<Orders>()
.Select(o => new { o.ShipName, o.OrderDate, o.Freight })
.ToList();
return Ok(data);
} catch (Exception ex) {
return BadRequest(ex);
}
}
#Implement Post and Put Methods
The ASP.NET Core runtime can populate model properties from the HTTP request body if a Controller method accepts a model as a parameter that has the FromBody
attribute.
To help the ASP.NET Core runtime create and load XPO models correctly, use XPO JSON Converters.
Add the following helper class to your project to register the XPO JSON Converters factory in an ASP.NET Core application:
using System;
using Microsoft.Extensions.Options;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Http;
using DevExpress.Xpo;
// ...
public class ConfigureJsonOptions : IConfigureOptions<JsonOptions>, IServiceProvider {
private readonly IHttpContextAccessor _httpContextAccessor;
private readonly IServiceProvider _serviceProvider;
public ConfigureJsonOptions(
IHttpContextAccessor httpContextAccessor,
IServiceProvider serviceProvider) {
_httpContextAccessor = httpContextAccessor;
_serviceProvider = serviceProvider;
}
public void Configure(JsonOptions options) {
options.JsonSerializerOptions.Converters.Add(new PersistentBaseConverterFactory(this));
}
public object GetService(Type serviceType) {
return (_httpContextAccessor.HttpContext?.RequestServices ?? _serviceProvider).GetService(serviceType);
}
}
Use this class in the application’s startup code as shown below:
builder.Services.ConfigureOptions<ConfigureJsonOptions>();
Tip
The Data Model Wizard adds the Configure
class to an ASP.
After you have enabled XPO JSON Converters, you can implement Post
and Put
methods as shown in the following code sample:
[HttpPost]
public IActionResult Post([FromBody] Customer customer) {
try {
uow.CommitChanges();
return NoContent();
} catch(Exception exception) {
return BadRequest(exception);
}
}
[HttpPut("{id}")]
public IActionResult Put(int id, [FromBody] Customer customer) {
if(id != customer.Oid)
return NotFound();
try {
uow.CommitChanges();
return NoContent();
} catch(Exception exception) {
return BadRequest(exception);
}
}
#Custom Metadata Provider
XPO models implement built-in service properties. To make sure that the ASP.NET Core framework will ignore service properties, extend the DefaultModelMetadataProvider component and register it as shown below:
using System;
using System.Linq;
using Microsoft.Extensions.Options;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.ModelBinding.Metadata;
using DevExpress.Xpo;
public class XpoMetadataProvider : DefaultModelMetadataProvider {
public XpoMetadataProvider(ICompositeMetadataDetailsProvider detailsProvider) : base(detailsProvider) {
}
public XpoMetadataProvider(ICompositeMetadataDetailsProvider detailsProvider, IOptions<MvcOptions> optionsAccessor) : base(detailsProvider, optionsAccessor) {
}
protected override DefaultMetadataDetails[] CreatePropertyDetails(ModelMetadataIdentity key) {
DefaultMetadataDetails[] result = base.CreatePropertyDetails(key);
if(typeof(PersistentBase).IsAssignableFrom(key.ModelType))
return result.Where(x => !IsServiceField(x.Key)).ToArray();
else
return result;
}
static bool IsServiceField(ModelMetadataIdentity identity) {
Type declaringType = identity.PropertyInfo.DeclaringType;
return declaringType == typeof(PersistentBase)
|| declaringType == typeof(XPBaseObject);
}
}
using Microsoft.Extensions.DependencyInjection;
using Microsoft.AspNetCore.Mvc.ModelBinding;
builder.Services.AddSingleton(typeof(IModelMetadataProvider), typeof(XpoMetadataProvider));
Tip
The Data Model Wizard adds the Xpo
class to an ASP.
#Add Required Services
#Using XPO Data Model Wizard
The XPO Data Model Wizard adds the ServiceCollectionExtensions.cs
and JsonSerializationHelper.cs
files to your project. These files extend the IServiceCollection
interface with helper methods required to add XPO components to the DI service container.
You can prepare an ASP.NET Core Web API project as follows:
- Install the
DevExpress.Xpo
NuGet package. - Follow the steps in the following help topic to create an XPO data model: Data Model Wizard.
- Modify the application’s startup code as shown below. If you copy this code, replace “Northwind” with your XPO data model name or choose appropriate methods from the IntelliSense window.
builder.Services.AddNorthwindAsXpoDefaultUnitOfWork(true, options =>
options.UseConnectionStringForNorthwind(Configuration));
builder.Services.AddNorthwindJsonOptions();
#Manually
- Refer to the following help topic that describes XPO Dependency Injection APIs: XPO Extensions for ASP.NET Core Dependency Injection.
- Add the XPOJsonOptions.cs file to your project: XPOJsonOptions.cs.
- Register XPO DI components in the application’s startup code as shown below.
builder.Services.AddXpoDefaultUnitOfWork(true, options =>
options.UseConnectionString(builder.Configuration.GetConnectionString("MSSqlServer"))
.UseAutoCreationOption(AutoCreateOption.DatabaseAndSchema)
.UseEntityTypes(new Type[] { typeof(StatisticInfo) }));
builder.Services.ConfigureOptions<ConfigureJsonOptions>();
builder.Services.AddSingleton(typeof(IModelMetadataProvider), typeof(XpoMetadataProvider));
#How the XPO JSON Serialization Works
#Serialization
- A JSON object contains all public properties except for collections.
- If a public property references another persistent object and this property does not have the Aggregated attribute, the corresponding JSON field contains only the object’s key.
- If a public property references another persistent object and this property has the Aggregated attribute, the corresponding JSON field contains an object literal.
- If a collection property does not have the Association attribute, the corresponding JSON field contains an array of objects.
#Deserialization
- If a JSON object contains a key member,
PersistentBaseConverter
attempts to load an object from a data store. If the corresponding object does not exist in the data store,PersistentBaseConverter
creates a new object. - If a JSON object does not contain a key member,
PersistentBaseConverter
creates a new object. PersistentBaseConverter
skips a JSON field if the corresponding property is read-only or does not exist in a persistent class.- If a property references another XPO object, the corresponding JSON field should contain a key value.
PersistentBaseConverter
loads a referenced object by key and updates the reference property. - If a property has the Aggregated attribute, the corresponding JSON field should contain an object literal.
PersistentBaseConverter
updates a referenced object’s properties directly.
#Optimistic Locking
Every JSON object should include the OptimisticLockField
property when sent to or received from the server if Optimistic Locking is enabled in a client-server application.
#A One-Click Solution for Role-based Access Control with Web API Services via XPO (FREE)
XAF’s Solution Wizard scaffolds a Web API Service with integrated authorization & CRUD operations powered by the XPO ORM library. You can use OAuth2, JWT, or custom strategies for authentication alongside tools like Postman or Swagger for API testing. The built-in security system also filters out secure server data based on permissions granted to users. These basic functions are available free-of-charge: .NET App Security & Web API – Free Offer from DevExpress.