Basic Web API with ASP.NET 5

I am going to create basic web API access to the contacts data I have been using in previous posts. To start with I added an API folder to my project to hold my API controller. Next I added a contacts controller to the API folder by right clicking on the folder and selecting add new item.

AddNewItem

From the add new item under DNX selected Web API Controller Class, entered a name and clicked add.

AddNewItemDialog

From the resulting code I removed all the actions except for two get functions.

[Route("api/[controller]")]
public class ContactsController : Controller
{
    private readonly ContactsDbContext _dbContext;

    public ContactsController(ContactsDbContext dbContext)
    {
        _dbContext = dbContext;
    }

    // GET: api/values
    [HttpGet]
    public async Task<IEnumerable<ContactModel>> Get()
    {
        return await GetContacts().ToListAsync();
    }

    // GET api/values/5
    [HttpGet("{id}")]
    public async Task<ContactModel> Get(int id)
    {
        return await GetContacts()
                     .Where(c => c.Id == id).FirstOrDefaultAsync();
    }

    private IQueryable GetContacts()
    {
        var contacts = from c in _dbContext.ContactModels
                                 .Include(c => c.AddressModels)
                                 .Include(c => c.EmailAddressModels)
                                 .Include(c => c.PhoneModels)
                       select c;
        return contacts;
    }
}

The above code contains a lot of new concepts I am going to break it down more.

[Route("api/[controller]")]
public class ContactsController : Controller

The first thing to notice is the route attribute on the class declaration. The route attribute is how the routing engine determines where to send requests. Using [controller] tells the routing engine to use the class name minus the word controller. For example the above route handles api/contacts.

private readonly ContactsDbContext _dbContext;

public ContactsController(ContactsDbContext dbContext)
{
    _dbContext = dbContext;
}

The constructor takes the DbContext needed to access contacts. Note that the context is being automatically injected via the constructor thanks to the fact that ASP.NET 5 now comes with dependency injection out of the box.

// GET: api/values
[HttpGet]
public async Task<IEnumerable<ContactModel>> Get()
{
    return await GetContacts().ToListAsync();
}

// GET api/values/5
[HttpGet("{id}")]
public async Task<ContactModel> Get(int id)
{
    return await GetContacts()
                 .Where(c => c.Id == id).FirstOrDefaultAsync();
}

First get function returns all contacts and the second returns a specific contact based on the contact’s ID.

private IQueryable<ContactModel> GetContacts()
{
    var contacts = from c in _dbContext.ContactModels
                             .Include(c => c.AddressModels)
                             .Include(c => c.EmailAddressModels)
                             .Include(c => c.PhoneModels)
                   select c;
    return contacts;
}

Note that the query contains three includes and each of the included classes contain a navigation property back to the main contact. For example here is the email address model.

public class ContactEmailModel
{
    public int ContactId { get; set; }
    public int Id { get; set; }
    [EmailAddress]
    public string Address { get; set; }

    public ContactModel Contact {get; set;}
}

All of the above compiles and seems to run fine, but will not provide a response. The navigation property for contact creates a circular reference that the response serializer throws an exception trying to serialize.

Thankfully the framework has a configuration option to work around this problem. In the ConfigureServices function of the Startup class add the following.

services.ConfigureMvcJson(options =>
{
    options.SerializerSettings.PreserveReferencesHandling = PreserveReferencesHandling.All;
});

The above options marks the Contact property as a reference and does not try to circularly serialize it.

Now by running the project and going to http://localhost:port/api/contacts/1 in the browser I get all the contact data related to the contact with an ID of 1. I recommend using something like Postman to make the result more readable if you don’t have a front end to display the data.

Viewing SQL for Entity Framework 7 Queries

While writing this post on dealing with entity framework and collections I needed a way to see what SQL queries entity framework was sending to the database. At the time I used Express Profiler for the task.

expressProfiler

To get up and running with Express Profiler enter the server and authorization information and click the play button. Each event is logged in the grid. When an event is selected the actual query will show in the panel below the grid. The clear function is also very handy. Just hit it before triggering the entity framework query that you want to see the SQL for to minimize the number of event that have to be gone through.

I came across Express Profiler while watching Julie Lerman’s Looking Ahead to Entity Framework 7 Pluralsight course. This course is one of the ones provided free with a MSDN subscription so there is no reason not to check it. The course is a good introduction to Entity Framework 7. Keep in mind that the course is using beta 4 so things have changed some since it was released.

With the release of ASP.NET 5 Beta 6 a new debug logger was added to log to Visual Studio’s output window. This new logger seemed like it would be useful for logging entity framework queries.

In project.json add a dependency for Microsoft.Framework.Logging.Debug.

"Microsoft.Framework.Logging.Debug" :  "1.0.0-beta6"

In the Configure function of the Startup class use the logger factory to add the new debug logger. This is done via the AddDebug extension method that comes when the new dependency was added above.

if (env.IsDevelopment())
{
    app.UseBrowserLink();
    app.UseErrorPage();
    app.UseDatabaseErrorPage(DatabaseErrorPageOptions.ShowAll);
    loggerfactory.AddDebug(LogLevel.Verbose);
}

Run the application and the output window will contain the SQL that is sent to the database. The downside to this approach is that the log level of verbose outputs a lot of information making it harder to locate the SQL bits.

New ASP.NET 5 Project Using Yeoman

One of the great things about ASP.NET 5 its openness and support for cross-platform development. This post is going to walk through using Yeoman to create a new ASP.NET 5 application and then run that application from the command line. This will give you the same application as Visual Studio just without the Visual Studio solution.

First make sure node.js is installed. The installer can be found here. Node comes with a package manager called npm automatically. Don’t know anything about npm? Watch this introductory video.

Yeoman is a scaffolding tool that uses templates called generators. First using the following command from the command prompt to install Yeoman. As a note all the commands in this post should be run from the command prompt.

npm install -g yo

Next install the generator for ASP.NET 5 which is provided by the OmniSharp team.

npm install -g generator-aspnet

Now tell Yeoman to run the ASP.NET 5 generator.

yo aspnet

Below is a screenshot of the results. This is where the type of application to be generated is chosen. In this case I am choosing a Web Application.

yoaspnet

Next enter the name of the application. In this case WebApp1.

yoaspnetWebApp1

After the creation process is done a set of commands are show as the next steps.

yoaspnetWebApp1GettingGoing

This command changes to the directory created during the generation process.

cd "WebApp1"

DNX Utility or dnu is a tool used to manage operations related to packages an application uses. The restore command finds all the dependencies of your application and downloads them. Not only does restore get the top level of dependencies but it also gets all the sub dependencies.

dnu restore

DNU build runs the build process to produce the assemblies for an application.

dnu build

DNX is a .NET execution environment. It contains all that is needed to run an application. The run command is for console applications as the output from the generator said and does not apply to a web application.

Kestrel is a development web server that works cross platform. The web command uses this project and only works on Windows I believe.

dnx . web

OR

dnx . kestrel

At this point a web server is running and should the application will be viewable in a browser on a local host address. The exact url can be found in the hosting.ini file of the project.

The list of commands defined for an application can be found in the project.json file command section. The command section defines named entry points for the application. The following is the commands section of WebApp1 which defines both kestrel and web.

"commands": {
  "kestrel": "Microsoft.AspNet.Hosting --server Kestrel --config hosting.ini",
  "web": "Microsoft.AspNet.Hosting --server Microsoft.AspNet.Server.WebListener --config hosting.ini"
}

Migration from ASP.NET 5 Beta 5 to Beta 6

ASP.NET 5 Beta 6 was released on July 27th with the details from Microsoft in this blog post.  This release comes with a tooling update for Visual Studio 2015 and fewer breaking changes than beta 5.

Download and install the tooling update from here. Grab either DotNetVersionManager-x64.msi or DotNetVersionManager-x86.msi depending on what your system supports and WebToolsExtensionsVS14.msi. For WebToolsExtensionsVS14.msi there are language pack versions available for languages other than english.

With the tooling updates installed the following changes were made from Visual Studio. In global.json update the sdk version to beta 6.

{
    "projects": [ "src", "test" ],
    "sdk": {
        "version": "1.0.0-beta6"
    }
}

For project.json in dependencies section update all the values from beta5 to beta6 except for  Microsoft.Framework.CodeGenerator.Mvc which stays at beta5.

"dependencies": {
  "EntityFramework.SqlServer": "7.0.0-beta6",
  "EntityFramework.Commands": "7.0.0-beta6",
  "Microsoft.AspNet.Mvc": "6.0.0-beta6",
  "Microsoft.AspNet.Mvc.TagHelpers": "6.0.0-beta6",
  "Microsoft.AspNet.Authentication.Cookies": "1.0.0-beta6",
  "Microsoft.AspNet.Authentication.Facebook": "1.0.0-beta6",
  "Microsoft.AspNet.Authentication.Google": "1.0.0-beta6",
  "Microsoft.AspNet.Authentication.MicrosoftAccount": "1.0.0-beta6",
  "Microsoft.AspNet.Authentication.Twitter": "1.0.0-beta6",
  "Microsoft.AspNet.Diagnostics": "1.0.0-beta6",
  "Microsoft.AspNet.Diagnostics.Entity": "7.0.0-beta6",
  "Microsoft.AspNet.Identity.EntityFramework": "3.0.0-beta6",
  "Microsoft.AspNet.Server.IIS": "1.0.0-beta6",
  "Microsoft.AspNet.Server.WebListener": "1.0.0-beta6",
  "Microsoft.AspNet.StaticFiles": "1.0.0-beta6",
  "Microsoft.AspNet.Tooling.Razor": "1.0.0-beta6",
  "Microsoft.Framework.Configuration.Json": "1.0.0-beta6",
  "Microsoft.Framework.Configuration.UserSecrets": "1.0.0-beta6",
  "Microsoft.Framework.CodeGenerators.Mvc": "1.0.0-beta5",
  "Microsoft.Framework.Logging": "1.0.0-beta6",
  "Microsoft.Framework.Logging.Console": "1.0.0-beta6",
  "Microsoft.VisualStudio.Web.BrowserLink.Loader": "14.0.0-beta6"
}

In Startup.cs in the configure function in the is development section I was able to enable browser link and the UseErrorPage dropped the show all option.

if (env.IsDevelopment())
{
    app.UseBrowserLink();
    app.UseErrorPage();
    app.UseDatabaseErrorPage(DatabaseErrorPageOptions.ShowAll);
}

The LogOff action of the AccountController changed to an async operation.

Before:
public IActionResult LogOff()
{
    SignInManager.SignOut();
    return RedirectToAction("Index", "Home");
}

After:
public async Task LogOff()
{
    await SignInManager.SignOutAsync();
    return RedirectToAction("Index", "Home");
}

The rest of the changes I had to make are entity framework related. The call to apply migrations no longer requires the as relation call.

Before:
Database.AsRelational().ApplyMigrations();

After:
Database.ApplyMigrations();

If you are trying to keep any existing migrations then changes will need to be made in them as well. There is a namespace change related to moving migrations out of the relational area.

Before:
Microsoft.Data.Entity.Relational.Migrations.Infrastructure

After:
Microsoft.Data.Entity.Migrations.Infrastructure

The settings on auto incremented properties changed as well.

Before:
b.Property<int>("ContactId")
    .GenerateValueOnAdd()
    .StoreGeneratedPattern(StoreGeneratedPattern.Identity);

After:
b.Property("ContactId")
    .ValueGeneratedOnAdd();

That is all there is to moving to beta 6 from beta 5. I am going to leave you with some reference links that may help if your project has issues with the move to beta 6.

Release page on Github with all the change in beta 6
Beta 6 Announcements Github page including breaking changes
ASP.NET 5 Roadmap

Entity Framework 7 with a Class that Contains Collections

In order to explore entity framework a bit more I took my existing contact class and broke it down to the following.

public class Contact
{
    public int ContactId { get; set; }
    public string UserId { get; set; }
    [Required]
    [StringLength(200, MinimumLength = 0)]
    public string Name { get; set; }
    public List<ContactAddress> Addresses { get; set; }
    public List<ContactPhone> Phones { get; set; }
    public List<ContactEmailAddress> EmailAddresses { get; set; } 
}

The following is the new email address model from it you will get the idea of what the address and phone models contain.

public class ContactEmailAddress
{
    public int ContactId { get; set; }
    public int EmailId { get; set; }
    [EmailAddress]
    public string Email { get; set; }

    public Contact Contact { get; set; }
}

Next up was the DbContext which got a new DbSet, set up keys and relationships between the models. Again I am limiting the example to contact and email addresses but the same concepts apply to the other related models.

public class ContactsDbContext : DbContext
{
    private static bool _created;
    public DbSet<Contact> Contacts { get; set; }
    public DbSet<ContactEmailAddress> ContactEmailAddresses { get; set; }

    public ContactsDbContext()
    {
        if (!_created)
        {
            Database.AsRelational().ApplyMigrations();
            _created = true;
        }
    }

    protected override void OnModelCreating(ModelBuilder builder)
    {
        builder.Entity<Contact>().Key(c => c.ContactId);

        builder.Entity<ContactEmailAddress>(entity =>
        {
            entity.Key(e => new { e.ContactId, e.EmailId });
            entity.Reference(e => e.Contact)
                  .InverseCollection(c => c.EmailAddresses)
                  .ForeignKey(e => e.ContactId);
        });
    }
}

In the above code the override of OnModelCreating establishes the connection between the models. InverseCollection establishes that there can be multiple email addresses for a single contact. I am not using it, but InverseReference would establish a one to one relationship.

After all the model changes are complete add a new migration from the command line using the following command. Then apply the migration by using the apply command or running the application if your application auto applies migrations.

dnx . ef migration add ContactsSplit --context ContactsDbContext

Here is an example query using this new class setup that include data from the contacts table and joins the email address table to get the related email addresses.

var contacts = from c in _db.Contacts
                         .Include(c => c.EmailAddresses)
               where c.UserId == User.GetUserId()
               select c;

The include statement above is what make entity framework eagerly load the data from the email address table. The default behavior would not load the email addresses. Also note that include statements can be chained as needed.

The following query is the same as above without eagerly loading the contact’s email addresses.

var contacts = from c in _db.Contacts
               where c.UserId == User.GetUserId()
               select c;

At this point the EmailAddresses property of the returned contacts would be null. To load the email addresses for a particular contact the following can be used.

_db.ContactEmailAddresses.Where(e => e.ContactId == contact.ContactId).Load();

This post on stackoverflow has a great set of tips related to collections with entity framework 7.

ASP.NET 5 Getting and Storing User Identity

My contacts application has login options but does not currently tie data to a specific user. In this post I am going to fix that problem.  Add a new user ID property to the Contact class for storing the user’s ID.

public string UserId { get; set; }

The change to contact model needs to be applied to the database. To do this use the following dnx command to add a new entity framework migration.

dnx . ef migration add AddContactUser --context ContactsDbContext

At this point a run of the application will apply the migration to the database. This is assuming use of Database.AsRelational().ApplyMigrations() in the constructor of the appropriate data context, if not then dnx can be used to apply the migration.

The ContactsContoller now needs to require a logged in user as well as get the ID for the logged in user. The following two using statements are need to be added to support these operations.

using System.Security.Claims;
using Microsoft.AspNet.Authorization;

Microsoft.AspNet.Authorization provides access to the authorize attribute which is used to require an authorized used. The authorize attribute can be used a the  class or on individual functions. This example is at the class level.

[Authorize]
public class ContactsController : Controller

System.Security.Claims provides an extension method on the controller’s User property to get the current user’s ID. The following is the code from the index action for the ContactsController with the added filter for user ID on the contacts query.

public IActionResult Index(string filter)
{
    var contacts = from c in _db.Contacts
                   where c.UserId == User.GetUserId()
                   select c;

    if (!string.IsNullOrEmpty(filter))
    {
        contacts = contacts.Where(c => c.Name.Contains(filter) ||
                                       c.Address.Contains(filter) ||
                                       c.City.Contains(filter) ||
                                       c.Email.Contains(filter) ||
                                       c.Phone.Contains(filter) ||
                                       c.State.Contains(filter) ||
                                       c.ZipCode.Contains(filter));
    }

    if (Request?.Headers != null && 
        Request.Headers["X-Requested-With"] == "XMLHttpRequest")
    {
        return PartialView("_ContactList",contacts);
    }

    return View(contacts);
}

A similar change needs to be made on all the actions in the ContactsController. For example here is the user ID being used as part of the create action.

[HttpPost]
[ValidateAntiForgeryToken]
public IActionResult Create(Contact contact)
{
    if (ModelState.IsValid)
    {
        contact.UserId = User.GetUserId();
        _db.Contacts.Add(contact);
        _db.SaveChanges();
        return RedirectToAction("Index");
    }

    return View(contact);
}

This method works fine but I am not sure if only using the User ID on the server-side is best practice or not. The other option would be to send the user ID to the client as a hidden field which would get returned when the user posted changes. It seems that forcing the User ID on the contact model on the server-side would prevent it from be tampered with, but this is a topic that I need to research further.

Starting Over with Entity Framework 7

Last week as part of a migration from ASP.NET 5 beta 4 to beta 5 I deleted all the entity framework migrations for a project. This post is going to walk through the process deleting the existing database, creating new migrations and applying the new migrations.

The first step is to delete the existing database associated with the project. To do this from within Visual Studio 2015 open the SQL Server Object Explorer. Click on the Add SQL Server button (second button).

SqlServerObjectExplorer

The add button launches the Connect to Server dialog. If using the default setup with SQL Server Express the settings below should work. After all the relevant information has been entered click connect.

SqlServerObjectExplorerConnectToServer

Right click on the database for the application and click delete.

SqlServerObjectExplorerDeleteDatabase

Another option would be to change the database name in the connection string which would also trigger entity framework to create a new database.

The next step is to add migrations for each DbContext in your project. The following two commands, run from the command prompt, will add migrations for the two contexts associated with my application.

dnx . ef migration add ApplicationInit --context ApplicationDbContext
dnx . ef migration add ContactsInit --context ContactsDbContext

The following is a repeat, but it is important part of the setup since in it is how this application applies migrations. The constructors of the DbContext classes apply migrations as demonstrated in the following code.

public class ContactsDbContext : DbContext
{
    private static bool _created;
    public DbSet<Contact> Contacts { get; set; }

    public ContactsDbContext()
    {
        if (!_created)
        {
            Database.AsRelational().ApplyMigrations();
            _created = true;
        }
    }
}

After the first run of the application a new database will be created and you will be ready to go with a fresh database.

Migration from ASP.NET Beta 4 to Beta 5

ASP.NET beta 5 was released on June 30th. See this blog post from Microsoft for details. I also recommend this video of the ASP.NET community standup from the day of the beta 5 release it has a lot of great information on the release and way forward for ASP.NET 5. This post is going to cover a migration of my contacts application from beta 4 to beta 5.

To start upgrade dnvm by opening a command prompt and running the following command.

dnvm update-self

After that is complete use dnvm to get beta 5 by running the following.

dnvm upgrade

The rest of the migration was performed from Visual Studio. Next up is an update to global.json to change the version from beta4 to beta5.

{
    "projects": [ "src", "test" ],
    "sdk": {
        "version": "1.0.0-beta5"
    }
}

In project.json the dependencies section needs values beta4 updated to beta5.

  "dependencies": {
    "EntityFramework.SqlServer": "7.0.0-beta5",
    "EntityFramework.Commands": "7.0.0-beta5",
    "Microsoft.AspNet.Mvc": "6.0.0-beta5",
    "Microsoft.AspNet.Mvc.TagHelpers": "6.0.0-beta5",
    "Microsoft.AspNet.Authentication.Cookies": "1.0.0-beta5",
    "Microsoft.AspNet.Authentication.Facebook": "1.0.0-beta5",
    "Microsoft.AspNet.Authentication.Google": "1.0.0-beta5",
    "Microsoft.AspNet.Authentication.MicrosoftAccount": "1.0.0-beta5",
    "Microsoft.AspNet.Authentication.Twitter": "1.0.0-beta5",
    "Microsoft.AspNet.Diagnostics": "1.0.0-beta5",
    "Microsoft.AspNet.Diagnostics.Entity": "7.0.0-beta5",
    "Microsoft.AspNet.Identity.EntityFramework": "3.0.0-beta5",
    "Microsoft.AspNet.Server.IIS": "1.0.0-beta5",
    "Microsoft.AspNet.Server.WebListener": "1.0.0-beta5",
    "Microsoft.AspNet.StaticFiles": "1.0.0-beta5",
    "Microsoft.AspNet.Tooling.Razor": "1.0.0-beta5",
    "Microsoft.Framework.CodeGenerators.Mvc": "1.0.0-beta5",
    "Microsoft.Framework.Configuration.Json": "1.0.0-beta5",
    "Microsoft.Framework.Configuration.UserSecrets": "1.0.0-beta5",
    "Microsoft.Framework.Logging": "1.0.0-beta5",
    "Microsoft.Framework.Logging.Console": "1.0.0-beta5",
    "Microsoft.VisualStudio.Web.BrowserLink.Loader": "14.0.0-beta5"
  }

One big thing here to note is that Microsoft.Framework.ConfigurationModel and all its children have been renamed to Microsof.Framework.Configuration. For example Microsoft.Framework.ConfigurationModel.Json is now Microsoft.Framework.Configuration.Json.

In the Views folder _GlobalImport.cshtml needs to be renamed to _ViewImports.cshtml.

Entity framework migrations had some issues as well, but I decided to just delete the existing migrations and start from scratch since the database contains a minimal amount of data.

The last set of changes are in Startup.cs. First up is a using change for the ConfigurationModel to Configuration rename.

Before:
using Microsoft.Framework.ConfigurationModel;

After:
using Microsoft.Framework.Configuration;

Next up is the Startup function. Here a builder has been added which is then used to create the actual configuration. Also note the added function parameter for IApplicationEnviroment which is used to get the application path for use by the configuration builder.

Before:
public Startup(IHostingEnvironment env)
{
    // Setup configuration sources.
    var configuration = new Configuration()
        .AddJsonFile("config.json")
        .AddJsonFile($"config.{env.EnvironmentName}.json", optional: true);

    if (env.IsEnvironment("Development"))
    {
        // This reads the configuration keys from the secret store.
        configuration.AddUserSecrets();
    }
    configuration.AddEnvironmentVariables();
    Configuration = configuration;
}

After:
public Startup(IHostingEnvironment env, IApplicationEnvironment appEnv)
{
    // Setup configuration sources.
    var configurationBuilder = new ConfigurationBuilder(appEnv.ApplicationBasePath)
        .AddJsonFile("config.json")
        .AddJsonFile($"config.{env.EnvironmentName}.json", true);

    if (env.IsEnvironment("Development"))
    {
        // This reads the configuration keys from the secret store.
        configurationBuilder.AddUserSecrets();
    }

    configurationBuilder.AddEnvironmentVariables();
    Configuration = configurationBuilder.Build();
    
}

In the ConfigureServices function Configuration.GetSubKey has been replaced by Configuration.GetConfigurationSection.

Before:
services.Configure<AppSettings>(Configuration.GetSubKey("AppSettings"));

After:
services.Configure<AppSettings>(Configuration.GetConfigurationSection("AppSettings"));

The last change was to remove app.UseBrowserLink. I am not thrilled with having to remove the use of browser link but it is throwing a System.TypeLoadException. I am going to keep looking for this issue but with UseBrowserLink commented out everything else works fine. If anyone else has this issue and finds a fix please leave a comment on how it was fixed.

If your application is still having trouble check out this page which contains a list of breaking changes from beta 4 to beta 5.

ASP.NET 5 Web Site to Azure

At the point the basics of my ASP.NET 4 contacts application have been moved to the ASP.NET 5. This is never going to be a production application, but I want it run it on a remote server just to prove it works. I decided to publish to Microsoft Azure which is Microsoft’s cloud offering. The process was a lot more challenging that I had expected, but as with all the rough spots I have hit with ASP.NET 5 I am sure the path will be made smooth for the final release.

Publishing to Azure from Visual Studio 2015 RC

To get started right click on the project to be published and select the Publish.

ProjectRightClickPublishMenu

This will load the Publish Web dialog. On the Profile tab select the Microsoft Azure Web Apps option.
PublishDialogProfile

This will show the Select Existing Web App dialog. Click the New button to add a new Web App.
AzureWebAppDialog

The new button show the Create Web App on Microsoft Azure. This dialog has a bit more to it. Web App name sets the url of the app as well as the app name with Azure. For region I just chose the closest data center. My application uses a database and I don’t have an existing database server in Azure so I chose Create new server for Database server selection. Database username and password are self explanatory. With all the options filled in click Create.
AzureCreateWebApp

After the creation process, which creates all the infrastructure need for the app in Azure, is done Visual Studio returns to the Publish Web dialog. The following is the Connection tab. The fields are editable, but are auto filled from the creation process. In case changes are need use the provided Validate Connection button to verify Visual Studio is still able to communicate with Azure.
PublishDialogConnection

The Settings tab allows selection of Release or Debug configurations as well as the target DNX version.
PublishDialogSettings

The last tab on the Publish Web dialog is Preview. It is not overly useful on a first publish since all the file for the project needed to be push, but on subsequent publishes it would be useful to verify nothing unexpected is being pushed.PublishDialogPreview

Pushing the Publish button on the Publish Web dialog push the files to Azure and opens a browser with the newly published web app.

Issues

After a few seconds I was greeted with a HTTP 500 Internal Server Error instead of my web app. I spent a lot of time on the Azure Portal trying to find my issue. I created a new project and published it without issue which means it is a problem with my app and not the publish process. I spent a lot of time digging and Googling my issues, but thankfully ended up with answers.

App Configuration

My first issues were the result of not setting up the configuration options for my user secrets. As I posted last week this was the main worry I had with user secrets. You would think with my concerns that would be the first thing I checked but it actually took me awhile to get around to checking my user secrets. Just to be clear I am not against user secrets I think they are an awesome feature I am just not used to dealing with this side of configuration. The steps to make the proper configuration for user secrets follow.

From the Azure Portal click Browse everything to get a list of all resources.

AzurePortal

From All resources click on the Web App that needs configuration. If you are paying close attention you will notice the name of my web app is different than the publication settings above. This is the result of one of my tries to get the site running before discovering the problem was configuration.
AzurePortalAllResources

Selecting a web app cause the details page to load. On the details page select Settings.
AzurePortalWebAppDetail

From the settings details page click Application Settings which will load the Web app settings page.AzurePortalWebAppSettings

In Web app settings scroll down to the App settings section. In my case I was missing the Authentication:Google:ClientId and Authentication:Google:ClientSecret settings used for OAuth with Google. Also make note of the Connection strings section as  this is the section where the connection string to the database needs to be entered.
AzurePortalWebAppSettingsAuthAndConnection

With all the above changes I was finally able to get the site to load.

Database/Entity Framework

As soon as I click on the contact list section of my app I got another HTTP 500 Internal Server Error. This happens to be the first time the app hits the database. The issue this time is that the DefaultConnection string that needs set so the app can connect to the database.

First step to fix this issue is to go back to the All resources on the Azure Portal and select the database that goes with the web app, aspnetcontacts_db in this example.

AzurePortalAllResourcesDb

This will load the SQL Database detail. Under Connection string is a link for Show database connection strings. Clicking this will load a page with a list of connection strings for this database. Copy the appropriate string and replace the dummy password with the real one. Take that connection string with the password enter and put it in your web app’s DefaultConnection. With the DefaultConnection set the 500 error went away.
AzurePortalDbDetailThe next time I ran I got a stack trace with a message that migrations needed to be run. In order to get migrations to run I made a few changes to my project.

The first change was in the ConfigureServices function of Startup.  I added the setup for the ContactsDbContext using the DefaultConnection string. In the ContactsDbContext I removed the OnConfiguring function which is where the connection string for the ContactsDbContext had been set before.

// Add EF services to the services container.
services.AddEntityFramework()
   .AddSqlServer()
   .AddDbContext<ApplicationDbContext>(options =>
       options.UseSqlServer(Configuration["Data:DefaultConnection:ConnectionString"]))
   .AddDbContext<ContactsDbContext>(options =>
       options.UseSqlServer(Configuration["Data:DefaultConnection:ConnectionString"]));

In order to actually run migrations for the ContactsDbContext I added a constructor with a call to Database.AsRelational().ApplyMigrations() which will ensure anytime the DbContext is constructed that the latest migrations will be applied. The following is the full ContactsDbContext class after the changes.

public class ContactsDbContext : DbContext
{
    private static bool _created;
    public DbSet<Contact> Contacts { get; set; }

    public ContactsDbContext()
    {
        if (!_created)
        {
            Database.AsRelational().ApplyMigrations();
            _created = true;
        }
    }
}

The last project change was to the ContactsController to allow ASP.NET to inject the ContactsDbContext instead of creating the context with in the controller.

private readonly ContactsDbContext _db;

public ContactsController(ContactsDbContext dbContext)
{
    _db = dbContext;
}

The change made above to the ConfigureServices function in the Startup class is how ASP.NET knows what to inject into the ContactsController. Build in dependence injection is one of the new features of ASP.NET 5.

After all the above changes I published to Azure and tried to access the contact list again. This resulted in a different error and a stack trace. The issue this round turned out to be that the default SQL Server created by Azure does not support the way that Entity Framework 7 is auto incrementing the ID column on contacts table. Thankfully there is an updated version of SQL available and the default server just need to be upgraded.

Back on the detail page for the SQL database there is a Server version listed as V2. Click the V2.

AzurePortalDbDetail

This will load the Latest SQL database update page. Click Upgrade This Server.

AzurePortalDbUpgrade

Currently the SQL Server created by the Visual Studio 2015 RC is in the Web tier which does not support the latest version of SQL which resulted in the warning below.
AzurePortalDbUpgradePriceWarningClick on your database name to load the Recommended pricing tier page. Since this is a new database Azure does not have enough information to recommend a tier and defaults to S0. At the very bottom of the page there is a big blue S0 link. Click it to change pricing tiers.

AzurePortalDbUpgradePriceRecommended

The Choose your pricing tier page will load. The current setting for the server is Web which shows as a retired. I chose the Basic tier but anything that is not marked as retired should support the newer version of SQL Server. After clicking on the option you want click the Select button at the bottom of the page.

AzurePortalDbUpgradePriceSelect

Now that the new pricing tier has been selected go back to the server details and click the V2 link under Server version. This round you will get a big warning. Under the warning enter the name of your server and click OK to perform the upgrade.

AzurePortalDbUpgradeTypeServerName

The upgrade process took less than 20 minutes for me. After the processes was complete the app worked as expected.

User Secrets

User secrets are a new concept in ASP.NET 5 which provide a way to use configuration values that are outside of the set of files that would be check into version control. An example of a good use case is the Google client ID and client secret I used in my OAuth post. This is information you would not want in a public repo.

If you are using the ASP.NET 5 Preview Web Site Template then user secrets is already set up and ready to go. If not check out this site which explains all about the user secrets functionality as well as how to use dnu to install the secret manager.

Even with user secrets already set up with the Visual Studio template I am going to point out some of the important bits.

In the project.json file there are a couple of items related to user secrets. The first item is the user secrets ID for the project. The ID seems to be a combination of the project name and some randomly generated text.

"userSecretsId": "Your Secret ID"

The next item in the project.json is in the dependencies section.

"Microsoft.Framework.ConfigurationModel.UserSecrets": "1.0.0-beta4"

The next reference is found in Startup.cs in the constructor where the rest of the configuration is set up.

if (env.IsEnvironment("Development"))
{
    configuration.AddUserSecrets();
}

configuration.AddEnvironmentVariables();

It is important to note that the last configuration added takes priority. Using the above configuration setup with user secrets added first and environment variables added second if both configurations contained a setting for connection string then the one in environment variables would be used. If the connection string did not exist in environment variables then the values from user secrets would be used.

To access user secrets right-click on the project file and select manage user secrets.

ManageUserSecretsMenu

The Manage User Secrets menu choice will open up the secrets.json file. This file will not be located anywhere in the project’s directory structure. The actual file location can be found at “%APPDATA%\Microsoft\UserSecrets\<userSecretsId>\” but you should not really need to know the location or edit the file outside of Visual Studio or user-secret command line tool. Especially while using the beta since the location may not be finalized.

This is my set up of my current secret.json which I am using to store the values needed for OAuth with Google.

{
  "Authentication": {
    "Google": {
      "ClientId": "Your Client Id",
      "ClientSecret": "Your Client Secret"
    }
  }
}

In Statup.cs the ConfigureServices function I was able to replace my hard-coded Client Id and Client Secret with values from my secrets.json.

services.Configure(options =>
{
    options.ClientId = Configuration["Authentication:Google:ClientId"];
    options.ClientSecret = Configuration["Authentication:Google:ClientSecret"];
});

With those changes above sensitive information will be less likely to accidentally get check in to GitHub or any other repo. The only concern I have with setup is a configuration value getting added to a developer’s user secret but that setting never making it into the other develops or production configurations. That worry exists even when checking in configuration to source control just seem more likely to get missed when the values are outside of the project. Even with that concern user secrets are a great features that should help prevent private information from making it out into the public.