3

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 (i.e. UserId, Security Token, etc.) plus some URL parameters (i.e. 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 (i.e. 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.

Parham
  • 31
  • 2

3 Answers3

0

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

  • Thank you Khaled for reply. I need to send the token and some other credential information from my .NET application to the angular universal app since they will be used to be passed for calling our API endpoints later on through the angular application. Is there any way to render the static pages that have been generated in server side automatically after creation? I am referring to angular server side by itself and not from .NET application. – Parham Aug 19 '21 at 19:16
  • In server.ts the following line seems to render the index.html, however that does not bootstrapping the entire application : res.render(indexHtml, {req, providers: [{provide: APP_BASE_HREF, useValue: req.baseUrl }] }) – Parham Aug 19 '21 at 19:24
  • Hi Khaled, Here is link of a sample angular universal project that I created in Github. https://github.com/Parham1381/repro-app – Parham Aug 24 '21 at 20:17
0

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 (i.e. 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.

NeNaD
  • 18,172
  • 8
  • 47
  • 89
  • Hi Nenad, I am not considering SEO optimization at this time and I just need to be able to run the server side application to get my request headers (i.e. Security Token) from a dedicated application and to pass them to a separate Java Based API Server with different endpoints, then to get the response from appropriate endpoint and to render the angular application using that response. – Parham Aug 25 '21 at 05:47
0

You need to use theSupplyData 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, falsein 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.

Pieterjan
  • 2,738
  • 4
  • 28
  • 55
  • Thank you Pieterjan for your reply. Please consider that caller application is completely a separate application which can be .NET, Java or simply an API testing tool (i.e. Postman). Regards to the angular server-side response that has not any styling or javascript libraries, if I open the url in the browser the application works properly, however when I am calling the url through a request in Http Client (same as ajax call), I am getting one incomplete static html page and not the entire angular application. – Parham Aug 25 '21 at 05:36
  • Do you get `ERROR`s in the VS output window when loading a page? – Pieterjan Aug 25 '21 at 05:48
  • It's hard to tell without having the backend code. Could you post the asp.net core project too? At first sight the only difference would be `types: ["node"]` missing in the `tsconfig.app.json`, which could possibly break the setup. – Pieterjan Aug 25 '21 at 07:22
  • I just modified the question and added a sample code in .NET Core (Windows Forms) to call the angular universal application – Parham Aug 25 '21 at 09:31