Aspnetcore-angular-universal: Populate AppInsights Key from Server

Created on 28 Jul 2017  路  24Comments  路  Source: TrilonIO/aspnetcore-angular-universal

I am storing my AppInsights Key in appSettings.json and I want to be able to inject into the NGModule, but not sure where to put it. I am adding it to TransferData in HomeController

TransferData transferData = new TransferData(); transferData.request = AbstractHttpContextRequestInfo(Request); transferData.AppInsightsId = "Foo";

But I am unclear how I get transferData.AppInsightsId into browser-app.module like in the description. I know that transferData is put on response.global, but I don't know how to get it on the TypeScript side

FAQ

Most helpful comment

And it's not hard, you made an insanely complex thing less complex. You are a hero

All 24 comments

Normally I'd use transfer state again on the browser which is filled from the object passed down. But in this case, just grab it directly off the window object. Check view source and you'll see the whole object at the bottom, should be easy to pluck it from there!

Hope that helps 馃憤

Cool, in the future is this the preferred way? I guess doing this in isPlatformBrowser() isn't a detriment

_Sent from my Samsung SM-G955U using FastHub_

The other thing you could do is make the API call to get the Key inside of APP_INITIALIZER (before angular even bootstraps), but this way is seems easier.

I'll try to work on improving docs and some of this Dev experience stuff in the coming week or so, I'll finally have time. The next goal is to improve JavaScriptServices, and then re-align the two repos more so people can use either one more easily (depending on what they want from their app).

So I must be doing something wrong because the Id isn't making it into the window object

Home Controller
TransferData transferData = new TransferData(); transferData.request = AbstractHttpContextRequestInfo(Request); transferData.AppInsightsId = "Foo";

main.server.ts
return ngAspnetCoreEngine(setupOptions).then(response => { // Apply your transferData to response.globals response.globals.transferData = createTransferScript({ AppInsightsId: params.data.AppInsightsId });

If I inspect the page, Window is empty

image

I am having the same issue as #342

Could this be related to SSR not working?

I'll take a peak tomorrow but it sounds related to whatever reason ssr stopped working for you.

I started the process of starting with a fresh clone and adding my bits to it to see what I am missing. I imagine it has to do with the coremodule and sharedmodule that I added to make appmodule lighter. If you see something glaring, a second set of eyes would help :)

Good idea, yeah duck punching might help figure out where the culprit is. I looked at the code a little bit earlier but nothing really stood out?

Let me know what it was when you do figure it out, curious!

Man this is a pain, can you give me some insight on how the template gets hydrated in this process? Should I assume that main.server.ts in dist is hydrated or needs to be hydrated?

It goes HomeController -> invokes main.server, which is passed the data through "params" -> main.server then invokes platform-server / universal to serialize the app to a string and take apart the other pieces (title/meta/links) passing them all back to HomeController. Then when MVC does it's thing is places everything where it needs to be.

If you made changes to main.server did you make identical changes to main.server.aot ?

If you put some console logs in main.server is actually getting all the pieces you need from the response aspnet engine?

Well I got it figured out. It was an issue with how I was making http request, I wasn't following your instructions at all. Now that I am using transferHttp, the resolver is working and the content and title are being rendered on the page when I view source. The meta tags were not rendering because I was doing this in app.component.ts

````
private getBaseUrl() {
if (Zone.current.get('originUrl')) {
return Zone.current.get('originUrl');
} else if (location) {
return location.href;
} else {
return 'something went wrong!';
}
}

metaData.push({ name: 'og:url', content: ${this.getBaseUrl()} });
````

I assume that this isn't an ok thing to do on server side. I need to find another way to get the full url so I can place that in meta and I will be good to go

You can get it from ORGIN_URL token we are passing down from the aspnet engine if I'm not mistaken.

馃憤馃巵馃憤馃憤
I'm glad you got it working though, sorry it wasn't easier!! I promise it'll be smoother in the future 馃槙

Nice, that gives me the base url... I want the whole thing (route included) I can figure it out I think ;)

And it's not hard, you made an insanely complex thing less complex. You are a hero

Thank you! Appreciate that 馃檹馃檹

Ok, one more weird thing I am noticing. I am passing the AppInsightsId through window and it is there on pre-render. However I get this message in console

An instrumentationKey value is required to initialize AppInsightsService

This code is in my browser-app.module
ApplicationInsightsModule.forRoot({ instrumentationKey: window['TRANSFER_CACHE']['AppInsightsId'] }),

When I view source, the value is there in TRANSFER_CACHE, do I need to be initializing the module somewhere else?

That is really strange, if you do a console log eve within the browser app module file for this it's really there as well? This should work ... damn transfer cache ! 馃槗馃槂

So I just got back to this. Works just fine in build:dev.. However if I have a console.log in main.server.aot, it says undefined. Main.server and main.server.aot are the exact same

main.server
```
import 'zone.js/dist/zone-node';
import './polyfills/server.polyfills';
import { enableProdMode } from '@angular/core';
import { INITIAL_CONFIG } from '@angular/platform-server';
import { APP_BASE_HREF } from '@angular/common';
import { createServerRenderer, RenderResult } from 'aspnet-prerendering';

import { ORIGIN_URL } from './app/shared/constants/baseurl.constants';
// Grab the (Node) server-specific NgModule
import { ServerAppModule } from './app/server-app.module';
// Temporary * the engine will be on npm soon (@universal/ng-aspnetcore-engine)
import { ngAspnetCoreEngine, IEngineOptions, createTransferScript } from './polyfills/temporary-aspnetcore-engine';

enableProdMode();

export default createServerRenderer((params: BootFuncParams) => {

// Platform-server provider configuration
const setupOptions: IEngineOptions = {
    appSelector: '<app></app>',
    ngModule: ServerAppModule,
    request: params,
    providers: [
        // Optional - Any other Server providers you want to pass (remember you'll have to provide them for the Browser as well)
    ]
};

return ngAspnetCoreEngine(setupOptions).then(response => {
    // Apply your transferData to response.globals
    response.globals.transferData = createTransferScript({
        AppInsightsId: params.data.appInsightsId,
        DiscusShortName: params.data.discusShortName
    });

    return ({
        html: response.html,
        globals: response.globals
    });
});

});

````

main.server.aot.ts

````
import 'zone.js/dist/zone-node';
import './polyfills/server.polyfills';
import { enableProdMode } from '@angular/core';
import { INITIAL_CONFIG } from '@angular/platform-server';
import { APP_BASE_HREF } from '@angular/common';
import { createServerRenderer, RenderResult } from 'aspnet-prerendering';

import { ORIGIN_URL } from './app/shared/constants/baseurl.constants';
// Grab the (Node) server-specific NgModule
import { ServerAppModuleNgFactory } from './ngfactory/app/server-app.module.ngfactory';
// Temporary * the engine will be on npm soon (@universal/ng-aspnetcore-engine)
import { ngAspnetCoreEngine, IEngineOptions, createTransferScript } from './polyfills/temporary-aspnetcore-engine';

enableProdMode();

export default createServerRenderer(params => {

// Platform-server provider configuration
const setupOptions: IEngineOptions = {
    appSelector: '<app></app>',
    ngModule: ServerAppModuleNgFactory,
    request: params,
    providers: [
        // Optional - Any other Server providers you want to pass (remember you'll have to provide them for the Browser as well)
    ]
};

return ngAspnetCoreEngine(setupOptions).then(response => {
    // Apply your transferData to response.globals
    response.globals.transferData = createTransferScript({
        AppInsightsId: params.data.appInsightsId,
        DiscusShortName: params.data.discusShortName
    });

    return ({
        html: response.html,
        globals: response.globals
    });
});

});

````

I put a console.log in browser-app.module

export function getRequest() { console.log(window['\n\n\n\n' + ['TRANSFER_CACHE']['AppInsightsId']+ '\n\n\n ']); // the Request object only lives on the server return { cookie: document.cookie }; }

Any ideas?

hey @MarkPieszak any thoughts on this?

Apologies, I'll take a look at this tomorrow, spent a few hours re-syncing with JSServices this evening, once I get that merged in here tomorrow, I can take a peak at this.

No worries, thanks Mark

I too would be interested in how do to this. In my case I'm trying to pass a google api key from dotnet to the client, and by using the following in app.module:

    AgmCoreModule.forRoot({
        apiKey: getGoogleApiKey(),
        libraries: ["places"]
    }),

export function getGoogleApiKey() {
if (typeof window !== 'undefined') {
return () => window['TRANSFER_CACHE']['googleApiKey'];
}
}

but although this works in dev, publishing to azure fails with "Function calls are not supported. Consider replacing the function or lambda with a reference to an exported function" errors. I've tried to move this code over to app.module.browser but when I do that it doesnt build at all because the components using the map fall over with "Can't bind to 'somepropertyname' since it isn't a known property of 'agm-map'" errors. Any suggestions on this would be gratefully received.

@MarkPieszak i tried again to do this with no luck :/

Was this page helpful?
0 / 5 - 0 ratings

Related issues

pjmagee picture pjmagee  路  17Comments

ardevik picture ardevik  路  14Comments

johnkattenhorn picture johnkattenhorn  路  15Comments

JohnGalt1717 picture JohnGalt1717  路  14Comments

georgiosd picture georgiosd  路  26Comments