-
Start with a new C# web app using ASP.NET 5 (Core 1.0)
- Select the Web API template (preview)
-
Open project.json and remove dnxcore50 from the frameworks section.
- Leave dnx451 under frameworks.
-
Add Entity Framework under dependencies in the project.json file.
- This should be the full EF 6.x.
-
Add a
DbConfig
class that extendsDbConfiguration
public class DbConfig : DbConfiguration { public DbConfig() { SetProviderServices("System.Data.SqlClient", SqlProviderServices.Instance); } }
-
Add a
Product
entity class.public class Product { public int Id { get; set; } public string ProductName { get; set; } public decimal UnitPrice { get; set; } }
-
Add a
SampleDbContext
inheriting fromDbContext
.- Place a
DbConfigurationType
attribute on it withDbConfig
. - Add a
Products
property of typeDbSet<Product>
[DbConfigurationType(typeof(DbConfig))] public class SampleDbContext : DbContext { public SampleDbContext(string connectionName) : base(connectionName) { } public DbSet<Product> Products { get; set; } }
- Place a
-
Optionally create a
SampleDbInitializer
class which inherits fromDropCreateDatabaseIfModelChanges<SampleDbContext>
.- Override the
Seed
method to see the database with data.
public class SampleDbInitializer : DropCreateDatabaseIfModelChanges<SampleDbContext> { protected override void Seed(SampleDbContext context) { var products = new List<Product> { new Product { Id = 1, ProductName = "Chai", UnitPrice = 10 }, new Product { Id = 2, ProductName = "Chang", UnitPrice = 11 }, new Product { Id = 3, ProductName = "Aniseed Syrup", UnitPrice = 12 }, }; context.Products.AddRange(products); context.SaveChanges(); } }
- Override the
-
Add a static ctor to
SampleDbContext
to set the context initializer.static SampleDbContext() { Database.SetInitializer(new SampleDbInitializer()); }
-
Add a "Data" section to appsettings.json with a connection string
- Here we specify LocalDb, but SQL Express or full is OK too.
"Data": { "SampleDb": { "ConnectionString": "Data Source=(localdb)\\MSSQLLocalDB;AttachDbFilename=|DataDirectory|\\SampleDb.mdf;Integrated Security=True; MultipleActiveResultSets=True" } }
-
Update the
Startup
ctor to set the "DataDirectory" for the currentAppDomain
.public Startup(IHostingEnvironment env, IApplicationEnvironment appEnv) { // Set up configuration sources. var builder = new ConfigurationBuilder() .AddJsonFile("appsettings.json") .AddEnvironmentVariables(); Configuration = builder.Build(); // Set up data directory string appRoot = appEnv.ApplicationBasePath; AppDomain.CurrentDomain.SetData("DataDirectory", Path.Combine(appRoot, "App_Data")); }
-
Register
SampleDbContext
with DI system by supplying a new instance ofSampleDbContext
- Add the following code to the
ConfigureServices
method inStartup
services.AddScoped(provider => { var connectionString = Configuration["Data:SampleDb:ConnectionString"]; return new SampleDbContext(connectionString); });
- Add the following code to the
-
Add a
ProductsController
that extendsController
- Pass
SampleDbContext
to the ctor - Add actions for GET, POST, PUT and DELETE
- Override
Dispose
to dispose of the context
[Route("api/[controller]")] public class ProductsController : Controller { private readonly SampleDbContext _dbContext; public ProductsController(SampleDbContext dbContext) { _dbContext = dbContext; } // GET: api/products [HttpGet] public async Task<ObjectResult> Get() { var products = await _dbContext.Products .OrderBy(e => e.ProductName) .ToListAsync(); return Ok(products); } // GET api/products/5 [HttpGet("{id}")] public async Task<ObjectResult> Get(int id) { var product = await _dbContext.Products .SingleOrDefaultAsync(e => e.Id == id); return Ok(product); } // POST api/products [HttpPost] public async Task<ObjectResult> Post([FromBody]Product product) { _dbContext.Entry(product).State = EntityState.Added; await _dbContext.SaveChangesAsync(); return Ok(product); } // PUT api/products/5 [HttpPut] public async Task<ObjectResult> Put([FromBody]Product product) { _dbContext.Entry(product).State = EntityState.Modified; await _dbContext.SaveChangesAsync(); return Ok(product); } // DELETE api/products/5 [HttpDelete("{id}")] public async Task<ActionResult> Delete(int id) { var product = await _dbContext.Products .SingleOrDefaultAsync(e => e.Id == id); if (product == null) return Ok(); _dbContext.Entry(product).State = EntityState.Deleted; await _dbContext.SaveChangesAsync(); return Ok(); } }
- Pass
-
Test the controller by running the app and submitting some requests.
- Use Postman or Fiddler
- Set Content-Type header to application/json for POST and PUT.
- The database should be created automatically
GET: http://localhost:49951/api/products POST: http://localhost:49951/api/products - Body: {"ProductName":"Ikura","UnitPrice":12} GET: http://localhost:49951/api/products/4 PUT: http://localhost:49951/api/products - Body: {"Id":4,"ProductName":"Ikura","UnitPrice":13} DELETE: http://localhost:49951/api/products/4