简体   繁体   中英

How to setup Angular Universal to be rendered in server side when it is being called through a Http Client request in .NET

I have an angular universal app (version 11) and I need to be able to call the application (get rendered in server side) through .NET Core HttpClient Request. I need to send some Http Headers (ie UserId, Security Token, etc.) plus some URL parameters (ie ProductId) to my angular universal app and am expecting the app (through server side) gets rendered properly, however only some static HTML tags gets returned after the call with no styling and no actual app to get running.

Please consider that if I open the server side URL in a browser, I am able to run the application only if I comment out the logic to consider the Http Headers.

Am I missing something or Angular Universal was not designed to be called through a Http Request (ie sending request using postman)?

Here is a sample project that I created in Github, to reproduce the bug there. https://github.com/Parham1381/repro-app

When I call the app through a browser, I can see it working properly, but when I open it using .NET Http Client, here is the result:

You can see a sample code in .NET core to call the angular universal application.

Angular Universal executes on the server, generating static application pages that later get bootstrapped on the client.

your call will render a static App, when you call it from the client side it will render the whole thing with functionalities and styles

your questions is a bit general, if you give more details about the problem you are trying to solve, maybe I can help you more, because sending token, user id and other parameters does not need the universal angular

Angular Universal is for server side rendering of the Angular app, and it is created because search engines couldn't see the app when crawling, so the app would never appear in the search. So, it is only for the SEO optimization purposes.

That said, if your pages will require Http Headers (ie UserId, Security Token, etc.), the search bots will not send these when crawling, so there is no point for you to have server side rendering. All the routes that you want to be indexed, has to be open (without required authentication) in order for search engine to crawl it and index it.

You need to use the SupplyData delegate of the SpaPrerenderingOptions

`options.SupplyData = (context, data) => {
    data["dataFromServer"] = new {
        // Here you can pass the data to angular
        item1 = "Hello world",
        item2 = 5,
        item3 = true
    };
}

This data becomes available in the main.server.ts at the call to createServerRenderer

export default createServerRenderer(params => {
    /* read params.data.dataFromServer */
    providers.push({
        provide: 'SERVER_SIDE',
        useValue: true
    }, {
        provide: 'DATA_FROM_SERVER',
        useValue: params.data.dataFromServer
    });
});

Then you can once again retrieve the values in your pages:

export class ArtistShowComponent {

  constructor(
    private route: ActivatedRoute,
    @Inject(SERVER_SIDE) serverSide: boolean,
    @Inject('DATA_FROM_SERVER') dataFromServer: any,
    ...
  ) {
    if (serverSide === true) {
      this.setArtist(dataFromServer.artist);
    } else {
      var id = parseInt(this.route.snapshot.paramMap.get('id'));
      this.loadArtist(id);
    }
  }

}

You can find a complete example here

I strongly recommend passing just a single object from .NET to angular-server-side, all the way through (I named it dataFromServer ). I didn't do it this way and I see the potential for errors now.

  • Have only one data["dataFromServer"] assignment
  • Add only 2 providers to your main.*.ts files:
    • SERVER_SIDE: true in main.server.ts, false in main.ts
    • DATA_FROM_SERVER: null in main.ts

Also to determine what page is to be rendered I created a nuget package

Note that the delegate passed to SupplyData can no longer be async .

As for the server-side rendered response lacking styling, you usually needed to update angular.json and set projects:ClientApp:architect:server:options:extractCss to true , but it seems like this was changed recently and it defaults to true now. I don't have it anymore in my angular.json and my website returns a fully styled ssr-response.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM