Sheldon Johnson Sheldon Johnson - 2 months ago 13x
AngularJS Question

How to specify different api URL in Azure deployment vs running locally?

So my setup is like this.

I have a solution with two projects. The first project is an ASP.NET WebAPI project that represents a REST API. It is completely view-less and returns only JSON responses for the API calls.

The second project is an AngularJS client. I started by creating an empty Web app in Visual Studio. So this project does have a Web.Config and an Azure publish profile but no C# controllers, routes, app_start, etc. It is all JavaScript and HTML.

The two projects are deployed as two independent Web Apps in Azure. Project_API and Project_Web.

My question is in my Angular App when the service responsible for communicating with the REST API how do I gracefully detect or set the URL based on whether I am deployed in Azure vs running locally?

// Use this api URL when running locally
var BaseURL = 'http://localhost:15774/api/games/';
// Use this api URL when deployed to Azure
// var BaseURL = '';

It is similar to how inside of the Project_API project I can set a different connection string for my local vs production database. That I understand though because the C# code can read the database connection string from Web.Config, and I can override that value in the Azure application settings for the deployed app. I guess I don't know the right way to do the similar action for a JavaScript client web app though.


The actual solution I went with was to create an ASP 5 project type. This project type has built-in support for the gulp task runner. It still feels a little bit unnatural to use Visual Studio to develop an AngularJS client in the first place, but at least this brings it closer to a common front-end webdev client development feel with the taskrunner support.

The other suggest solution I am sure works also. It just seems to me that if you choose:

  1. To separate your REST API and client front-end into separate independent projects rather than serving up both your client and server from a single project.
  2. Write your front-end client as an Angular SPA.

Then it would be undesirable to have to use C# and Razor in the Angular client. That might be common in traditional ASP development, but not common and standard in most Angular client development. Using taskrunners for Angular clients seems more like the general practice. However, as the previous solution points out at this time it is brand new for Visual Studio to support this.

Rest of the details for my solution:

  1. Pull into gulp a new module/dependency: gulp-ng-constant

  2. Create app/config.json:

    { "development": { "ApiEndpoint": "http://localhost:15774/api/games/" }, "production":{ "ApiEndpoint": "" } }

  3. Setup new gulp task: "gulp config" Set this task to call the ngConstant function that comes with gulp-ng-constant. Have it load the development settings from the config file:

    var myConfig = require(paths.webroot + 'js/app/config.json'); var envConfig = myConfig["development"];

Follow gulp-ng-constant documentation to specify any options and specify the name of which Angular module you want the constants to be registered in.
Bind this new task to the after-build event in task-runner explorer, so it will run after every build.

  1. Setup new gulp task: gulp production:config Make it exactly the same as step 3, except myConfig["production"] Don't bind it to the after-build event, rather add it to the pre-publish tasks in your project.json file:

    "prepublish": [ "npm install", "bower install", "gulp clean", "gulp production:config", "gulp min" ]

Now whenever you build and/or publish the gulp task will automatically generate a file /app/ngConstants.js. If you setup the task correctly the file will contain the Angular code to register the constants with the correct module.

 angular.module("game", [])
        .constant("ApiEndpoint", "http://localhost:15774/api/games/")

The only thing I don't really like about this solution is that there is no obvious way to tell in gulp if a build is "Debug" vs "Release". Reading some forums it sounds like the VS team is aware of this issue and planning to fix it in the future. It needs some method to expose the build config to the taskrunner. In my solution it will write the "development" constants every build and then it overwrites them to "production" values on publish. This works for this API endpoint case, but other constants might have different requirements and need that release vs debug configuration or you would be forced to run the release tasks by hand which might be acceptable depending on how often you are running the release build locally.