2

I'm creating a web site that makes calls to a WCF service that we host. Notice that the URL is hard-code in the JS:

    var config = {
        url: 'http://serverName:8000/MmaWebApiService/CreateCassette',
        method: 'POST',
        contentType: 'application/json; charset=utf-8',
        data: { 'moduleSerialNumbers': 'dataHere' }
    };

Where are we supposed to store URLs? I would think the web.config file would be a good spot, but I'm not sure how to access it. One suggestion is something like this:

<img id="ImgHeader" runat="server" src="<%$ ConfigurationSettings.AppSettings["ImagePath"] %>" />

However, I don't think that will work with my plain ol' HTML page, using AngularJS. I'm at a bit of a loss as to where to store service URLs so I don't have them hard-coded all over my JS. For example, if we deploy to a different server, I don't want to have to find all calls in JS and replace the server name. I must be missing a best practice.

Community
  • 1
  • 1
Bob Horn
  • 33,387
  • 34
  • 113
  • 219
  • It all kind of depends. You could use the method you mentioned before. At my company we populate an object in the main layout with various URLs provided by the server. [You can read from Web.config using `ConfigurationManager.AppSettings`](http://stackoverflow.com/questions/3854777/read-variable-from-web-config). – Mike Cluck Mar 22 '16 at 19:23
  • You could just put them in a .js file and include the script in the header. In a single page app, I've usually stored them in a .json file and loaded it via ajax call when required. – Jesse Lee Mar 22 '16 at 19:30
  • Mike: I don't think I can use ConfigurationManager in JS. Jesse: Good tip. I may try that. Thanks! – Bob Horn Mar 22 '16 at 19:36
  • Are you using a javascript task runner like gulp or grunt? If so, you can go the route of `app.constant(...)` and then have your task runner figure out what to do based on if you ran, for example, `gulp dev` or `gulp prod` – Tom Mar 23 '16 at 17:14
  • 1
    The fact that this was closed as opinion-based is ridiculous. Someone needs to know how to do something and it gets closed because others may have differing opinions. Frustrating. – Bob Horn Mar 27 '16 at 15:33
  • I found a good approach, and I was going to post it as an answer, but now I can't because it's closed. – Bob Horn Apr 22 '16 at 18:50

2 Answers2

2

Angular lets you define constants in the module setup.

angular.module('app').constant(
    ENDPOINT, {
        "URL": 'http://serverName:8000/MmaWebApiService/CreateCassette'
    }
);

You now have a constant that can be injected into a controller or service as per usual.

angular.application('app').controller('myCtrl', myCtrl);
myCtrl.$inject['ENDPOINT'];
function myCtrl(ENDPOINT) {
    var myUrl = ENDPOINT.URL;
}
The Head Rush
  • 3,157
  • 2
  • 25
  • 45
  • Interesting. I wonder if that's a better approach than what Jesse suggested: just put the URLs in a JS file. – Bob Horn Mar 22 '16 at 19:36
  • Well, your Angular app won't start if it can't find the module configuration. It will run (albeit poorly) if it can't load an external configuration file. – The Head Rush Mar 22 '16 at 19:42
  • What about the deployment story? How do you change URLs based on deploying to QA or prod? Is that a manual step? – Bob Horn Mar 22 '16 at 20:04
2

Since the correct URL is determined at deployment time, it's a deployment concern. So I used our deployment tool (Presto) to modify the URL during the deployment process. I ended up storing the root URL in index.html:

enter image description here

Notice that I gave it an ID (connection) so it can be altered later by our deployment app.

Then, in my AngularJS controllers, I use it like this:

        var config = {
            url: rootWebApiUrl + '/api/Cassette',
            method: 'POST',
            contentType: 'application/json; charset=utf-8',
            data: [$scope.state.subId1, $scope.state.subId2, $scope.state.subId3]
        };

I set Presto to modify the URL at deployment time by setting the URL to the name of the server where the Web API is being deployed.

enter image description here

There is a slight issue with this approach: The index.html has to be able to be XML-parsable in order for the deployment app to modify it. That means I had to alter some lines, like this:

Must be uppercase:

<!DOCTYPE html[]>

Must close any meta tags (need the closing forward slash):

<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes" />

ng-view has to have =”” after it:

<div ng-view="">

I made those changes and the app still runs. So I think I’m good.

Bob Horn
  • 33,387
  • 34
  • 113
  • 219