2

For security reason, we have to stick to ASP.NET MVC5. That's why we have to build the frontend Angular app and use BundleConfig to package and grab everything. For the view, we established a view placeholder for our Angular App.

Yes, I agree that it's ugly. However, it seems it is a best solution for us.

Here is the problem: When I try to load the static files. (e.g. images, json files) we have to grab them from the mvc5 backend.

I tried to move the static files to the angular assets folder, and everything got successfully compiled and copied to the dist folder. However, using relative path, Angular cannot recognize them.

Here is the error:

enter image description here

As you may know that the root of our angular app is: http://localhost:1220/client

and the absolute json file location is: 'http://localhost:1220/client/dist/assets/data/UiData.json'

This is my Angular service:

import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Observable } from 'rxjs/observable';

@Injectable()
export class LocalDataService {
  private staticDataURL = '../../../assets/data/UiData.json';
  // private staticDataURL = 'assets/data/UiData.json';

  constructor(private http: HttpClient) { }

  public getJSON(): Observable<any> {
    return this.http.get(this.staticDataURL);
  }
}

both path '../../../assets/data/UiData.json' and 'assets/data/UiData.json' won't work for this case, because the server won't recognize the frontend Angular App.

This is the BundleConfig from our MVC5 backend:

public class BundleConfig
{
    // For more information on bundling, visit https://go.microsoft.com/fwlink/?LinkId=301862
    public static void RegisterBundles(BundleCollection bundles)
    {
        bundles.Add(new ScriptBundle("~/script/bundle").Include("~/Scripts/dist/bundle.js"));
        bundles.Add(new StyleBundle("~/style/main").Include("~/Scripts/dist/style.css", new CssRewriteUrlTransform()));

        // Angular build artifacts
        bundles.Add(new ScriptBundle("~/script/report-bundle").Include(
            "~/client/dist/runtime.*",
            "~/client/dist/polyfills.*",
            "~/client/dist/scripts.*",
            "~/client/dist/main.*"
            ));

        bundles.Add(new StyleBundle("~/style/report-style")
            .Include(
                "~/client/dist/styles.*",
                new CssRewriteUrlTransform()
            ));
    }
}

Is there any way to load the local json file using relative path in this case?

Thanks in advance!

Terence
  • 652
  • 11
  • 34
  • 1
    It works if I change the path to `../client/dist/assets/data/UiData.json` but it is very ugly... – Terence Jul 15 '18 at 08:42
  • are you using @angular/cli – Michael Kang Jul 15 '18 at 08:47
  • I'm unfamiliar with asp.net but if I tried to do this in Java I would create a GET Rest endpoint returning the static JSON file that angular could call instead of trying to get the file directly. – SHN Jul 15 '18 at 08:49
  • @pixelbits yes, I'm using angular/cli and the angular.json is correctly configured. – Terence Jul 15 '18 at 09:11
  • @S.H.N that's good point. But it's not convenient...I tried to separate the front-end code a little bit more by moving the logic to the front-end. It feels dumb to mock the data for the unit tests when the data is there already. – Terence Jul 15 '18 at 09:15
  • @Terence just curious if you found a good solution for this... we're using angular-material theme files now, and still haven't found a much better solution – JBoothUA Sep 19 '18 at 20:59

1 Answers1

2

We have a very similar environment (for security reasons also). I'm hoping I can help answer your question by explaining what I 'think' would be the standard way to handle this...

I think the main thing is to just know / decide on a folder to treat as your "web root folder".

In older versions of MVC, it was the /Content folder. In asp.net core versions, it is the /wwwroot folder.

And then put all of your scripts and assets in that folder.. As long as they are all relative to each other it should work..

So basically, you'll want to edit your output dir of your angular-cli to output your angular app to something like

/Content/js/dist/your files

All of your assets will be in something like /Content/images/your images and /Content/static/your static files

something like that. in other words, you'll put all your assets in that "web root folder" and also make sure to output your /dist folder to that same folder.

hope that helps!

JBoothUA
  • 3,040
  • 3
  • 17
  • 46
  • 1
    Thanks Jesse. That's a pretty good solution. It keeps the absolute path consistent. However, we would like to put the image, font, static data in angular: `src/assets`. Do you suggest to configure that folder in Angular-cli? – Terence Aug 08 '18 at 23:47
  • 1
    i'll start out by saying I dont love this solution, but I think that at this time we would use an additional build step (tagged onto the end of your npm run "build" script) to copy the assets to the needed absolute path. I feel like the CLI team will improve on how they handle assets at some point, but they haven't yet. We ran into this same issue recently with Angular 6 packages. The Angular 6 build command for a library will copy the /assets folder.. But now you just have that library's assets stuck down in some /node_modules/libary-name/dist/assets folder. – JBoothUA Aug 09 '18 at 14:27
  • 1
    so for now we've used an extra command to handle assets. basically our common website uses this build command, I guess I would recommend something similar for assets at this point.. hopefully the CLI team will figure out a way to handle assets, but I know it's a security issue for them to write out files to outside of the /dist folder :: "build": "ng build --prod --output-hashing none && @powershell copy -R -force node_modules/@galileo/common-libraries/assets ../CommonSiteService/wwwroot", – JBoothUA Aug 09 '18 at 14:30
  • 1
    Thank you so much for your input. I am concern about the unit test for angular side. I really want to do it in a proper way. – Terence Aug 09 '18 at 19:05
  • as far as I know that is the 'standard'est way you're going to find :) please let me know if you find something better. as far as unit tests it works out perfectly for us. when you're dev testing or unit testing the library you have all your assets in the assets folder, but when the library is used by a site (pulled into node_modules) a script takes the assets out and puts them into a web root folder, and i believe that's basically what you would be doing. – JBoothUA Aug 09 '18 at 22:25
  • just because i was recently looking into this, the only other options I saw was someone had a "ng build && node copy-assets.js" and had a little js file to do all the copying – JBoothUA Aug 09 '18 at 22:30
  • looking back at my notes, something you might have some luck with (and would be a standard) would be something like this: "assets": [ { "glob": "**/*", "input": "src/assets/", "output": "/assets/" }, " in order to copy your assets to the correct web root folder.. (we were not able to use this because they are not really supported in Angular 6 libraries yet, but you might find it useful!) – JBoothUA Aug 09 '18 at 22:30
  • 1
    Thanks Jesse! I really appreciate your detailed comments. I'll definitely keep an eye out for a better solution. Meanwhile, I'll give your solution a try. – Terence Aug 09 '18 at 22:36
  • @Terence just curious if you found a good solution for this... we're using angular-material theme files now, and still haven't found a much better solution – JBoothUA Sep 19 '18 at 20:59