Skip to content

ASP.NET MVC Controller Example with Async

rdhainaut edited this page Nov 15, 2017 · 2 revisions

Basic sample of using the framework in an ASP.NET MVC 5 Controller. In real world this would most like be injected with an IService which would facilitate business logic and injected with necessary Repositories.

Use your choice of a DI & IoC framework, although DI & IoC are not required, it is highly recommended.

Using Unity for DI & IoC

Northwind.Web.App_Start.UnityConfig.cs

public static void RegisterTypes(IUnityContainer container)
{
    container
        .RegisterType<IDataContextAsync, NorthwindContext>(new PerRequestLifetimeManager())
        .RegisterType<IUnitOfWorkAsync, UnitOfWork>(new PerRequestLifetimeManager())
        .RegisterType<IRepositoryAsync<Customer>, Repository<Customer>>();
}

Northwind.Api.CustomerController.cs

public class CustomerController : ODataController
{
    private readonly IRepositoryAsync<Customer> _customerRepository;
    private readonly IUnitOfWorkAsync _unitOfWorkAsync;

    public CustomerController(
        IUnitOfWorkAsync unitOfWorkAsync,
        IRepositoryAsync<Customer> customerRepository)
    {
        _unitOfWorkAsync = unitOfWorkAsync;
        _customerRepository = customerRepository;
    }

    // GET odata/Customer
    public IQueryable<Customer> GetCustomer()
    {
        return _customerRepository.Queryable();
    }

    // GET odata/Customer(5)
    [Queryable]
    public SingleResult<Customer> GetCustomer(string key)
    {
        return SingleResult.Create(
            _customerRepository
                .Query(customer => customer.CustomerID == key)
                .Select()
                .AsQueryable());
    }

    // PUT odata/Customer(5)
    public async Task<IHttpActionResult> Put(string key, Customer customer)
    {
        if (!ModelState.IsValid)
        {
            return BadRequest(ModelState);
        }

        if (key != customer.CustomerID)
        {
            return BadRequest();
        }

        customer.ObjectState = ObjectState.Modified;
        _customerRepository.Update(customer);

        try
        {
            await _unitOfWorkAsync.SaveChangesAsync();
        }
        catch (DbUpdateConcurrencyException)
        {
            if (!CustomerExists(key))
            {
                return NotFound();
            }
            throw;
        }

        return Updated(customer);
    }

    // POST odata/Customer
    public async Task<IHttpActionResult> Post(Customer customer)
    {
        if (!ModelState.IsValid)
        {
            return BadRequest(ModelState);
        }

        _customerRepository.Insert(customer);

        try
        {
            await _unitOfWorkAsync.SaveChangesAsync();
        }
        catch (DbUpdateException)
        {
            if (CustomerExists(customer.CustomerID))
            {
                return Conflict();
            }
            throw;
        }

        return Created(customer);
    }

    // PATCH odata/Customer(5)
    [AcceptVerbs("PATCH", "MERGE")]
    public async Task<IHttpActionResult> Patch(string key, Delta<Customer> patch)
    {
        if (!ModelState.IsValid)
        {
            return BadRequest(ModelState);
        }

        var customer = await _customerRepository.FindAsync(key);

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

        patch.Patch(customer);

        _customerRepository.Update(customer);

        try
        {
            customer.ObjectState = ObjectState.Modified;
            await _unitOfWorkAsync.SaveChangesAsync();
        }
        catch (DbUpdateConcurrencyException)
        {
            if (!CustomerExists(key))
            {
                return NotFound();
            }
            throw;
        }

        return Updated(customer);
    }

    // DELETE odata/Customer(5)
    public async Task<IHttpActionResult> Delete(string key)
    {
        var customer = await _customerRepository.FindAsync(key);
        if (customer == null)
        {
            return NotFound();
        }

        _customerRepository.Delete(customer);
        await _unitOfWorkAsync.SaveChangesAsync();

        return StatusCode(HttpStatusCode.NoContent);
    }

    // GET odata/Customer(5)/CustomerDemographics
    [Queryable]
    public IQueryable<CustomerDemographic> GetCustomerDemographics(string key)
    {
        return _customerRepository.Query(m => m.CustomerID == key)
            .Select()
            .AsQueryable()
            .SelectMany(m => m.CustomerDemographics);
    }

    // GET odata/Customer(5)/Orders
    [Queryable]
    public IQueryable<Order> GetOrders(string key)
    {
        return _customerRepository
            .Query(m => m.CustomerID == key)
            .Select()
            .AsQueryable()
            .SelectMany(m => m.Orders);
    }

    protected override void Dispose(bool disposing)
    {
        if (disposing)
        {
            _unitOfWorkAsync.Dispose();
        }
        base.Dispose(disposing);
    }

    private bool CustomerExists(string key)
    {
        return _customerRepository.Query(e => e.CustomerID == key).Select().Any();
    }
}