This guide walks you through setting up WebServiceToolkit in an ASP.NET Core project.
- .NET 10 SDK or later
- An ASP.NET Core Web API project
The main package includes all dependencies:
dotnet add package DevInstance.WebServiceToolkitIf you only need specific functionality:
# Common models only (no ASP.NET Core dependency)
dotnet add package DevInstance.WebServiceToolkit.Common
# Database query interfaces only
dotnet add package DevInstance.WebServiceToolkit.DatabaseIn your Program.cs, register the WebServiceToolkit services:
using DevInstance.WebServiceToolkit.Http.Query;
using DevInstance.WebServiceToolkit.Tools;
var builder = WebApplication.CreateBuilder(args);
// Add controllers with query model binding
builder.Services.AddControllers()
.AddWebServiceToolkitQuery();
// Auto-register services marked with [WebService] attribute
builder.Services.AddServerWebServices();
var app = builder.Build();
app.MapControllers();
app.Run();Create a model class that implements IModelItem, and a list response type that implements IModelList<T>:
using DevInstance.WebServiceToolkit.Common.Model;
public class Product : IModelItem
{
public string Id { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public decimal Price { get; set; }
public string Category { get; set; }
}
public class ProductList : IModelList<Product>
{
public int TotalCount { get; set; }
public int PagesCount { get; set; }
public int Page { get; set; }
public int Count { get; set; }
public string[] SortOrder { get; set; }
public string Search { get; set; }
public Product[] Items { get; set; }
}
ModelItemandModelList<T>are obsolete. ImplementIModelItemandIModelList<T>on your own types instead.
Define a query model for filtering/pagination:
using DevInstance.WebServiceToolkit.Http.Query;
using System.ComponentModel;
[QueryModel]
public class ProductQuery
{
[DefaultValue(0)]
public int Page { get; set; }
[DefaultValue(20)]
public int PageSize { get; set; }
public string? Search { get; set; }
[QueryName("sort")]
public string? SortBy { get; set; }
[DefaultValue(true)]
public bool IsAscending { get; set; }
public string? Category { get; set; }
}Create a service interface and implementation:
using DevInstance.WebServiceToolkit.Common.Model;
using DevInstance.WebServiceToolkit.Common.Tools;
using DevInstance.WebServiceToolkit.Tools;
public interface IProductService
{
Task<ProductList> GetProductsAsync(ProductQuery query);
Task<Product?> GetByIdAsync(string id);
Task<Product> CreateAsync(CreateProductRequest request);
Task<Product> UpdateAsync(string id, UpdateProductRequest request);
Task DeleteAsync(string id);
}
[WebService]
public class ProductService : IProductService
{
private readonly IProductRepository _repository;
public ProductService(IProductRepository repository)
{
_repository = repository;
}
public async Task<ProductList> GetProductsAsync(ProductQuery query)
{
var products = await _repository.QueryAsync(query);
var totalCount = await _repository.CountAsync(query);
return ModelListResult.CreateList<ProductList, Product>(
products.ToArray(),
totalCount: totalCount,
top: query.PageSize,
page: query.Page,
sortOrder: query.SortBy == null ? null : new[] { (query.IsAscending ? "+" : "-") + query.SortBy },
search: query.Search);
}
public async Task<Product?> GetByIdAsync(string id)
{
return await _repository.FindByIdAsync(id);
}
// ... other methods
}Create a controller that uses the service:
using DevInstance.WebServiceToolkit.Common.Model;
using DevInstance.WebServiceToolkit.Controllers;
using DevInstance.WebServiceToolkit.Exceptions;
using Microsoft.AspNetCore.Mvc;
[ApiController]
[Route("api/[controller]")]
public class ProductsController : ControllerBase
{
private readonly IProductService _productService;
public ProductsController(IProductService productService)
{
_productService = productService;
}
[HttpGet]
public Task<ActionResult<ProductList>> GetProducts(ProductQuery query)
{
return this.HandleWebRequestAsync<ProductList>(async () =>
{
var products = await _productService.GetProductsAsync(query);
return Ok(products);
});
}
[HttpGet("{id}")]
public Task<ActionResult<Product>> GetProduct(string id)
{
return this.HandleWebRequestAsync<Product>(async () =>
{
var product = await _productService.GetByIdAsync(id);
if (product == null)
throw new RecordNotFoundException(id);
return Ok(product);
});
}
[HttpPost]
public Task<ActionResult<Product>> CreateProduct(CreateProductRequest request)
{
return this.HandleWebRequestAsync<Product>(async () =>
{
var product = await _productService.CreateAsync(request);
return CreatedAtAction(nameof(GetProduct), new { id = product.Id }, product);
});
}
[HttpPut("{id}")]
public Task<ActionResult<Product>> UpdateProduct(string id, UpdateProductRequest request)
{
return this.HandleWebRequestAsync<Product>(async () =>
{
var product = await _productService.UpdateAsync(id, request);
return Ok(product);
});
}
[HttpDelete("{id}")]
public Task<ActionResult<bool>> DeleteProduct(string id)
{
return this.HandleWebRequestAsync<bool>(async () =>
{
await _productService.DeleteAsync(id);
return Ok(true);
});
}
}Once your application is running, you can test the endpoints:
# Get all products with pagination
curl "http://localhost:5000/api/products?page=0&pageSize=10"
# Search for products
curl "http://localhost:5000/api/products?search=widget&sort=name"
# Get a specific product
curl "http://localhost:5000/api/products/abc123"
# Create a product
curl -X POST "http://localhost:5000/api/products" \
-H "Content-Type: application/json" \
-d '{"name":"Widget","price":9.99}'- Query Model Binding - Learn more about query parameter binding
- Exception Handling - Understand exception-to-HTTP mapping
- Service Registration - Auto-register services with DI
- Database Queries - Build fluent query objects
- Pagination - Implement paginated responses