Jun 06 2017 09:26 PM
Jun 06 2017 09:26 PM
I noticed today it was released the documentation about Sharepoint Framework Extensions and I wanted to give it a try.
I followed the steps on the tutorials, with the only difference that instead of doing a console.log or alert, I want to inject App Insights Code.
1. The code compiles fine, gulp serve works fine.
2. I can debug it as shown in the tutorials, without any problem, I can see the console with the messages I created on the TS file.
3. I changed the CDN path to Documents folder, yeah I know not a CDN, but I dont think this has something to do, (Oh yes I uploaded the js files to the documents library)
I am going to need to paste some large code here for you to get the idea:
package-solution.json
{ "solution": { "name": "app-insights-demo-sp-fx-extension-client-side-solution", "id": "02d35a3e-5896-4664-874f-9fe9fdfe8408", "version": "1.0.0.0", "features": [{ "title": "Application Extension - Deployment of custom action.", "description": "Deploys a custom action with ClientSideComponentId association", "id": "456da147-ced2-3036-b564-8dad5c1c2e34", "version": "1.0.0.0", "assets": { "elementManifests": [ "elements.xml" ] } }] }, "paths": { "zippedPackage": "solution/app-insights-demo-sp-fx-extension.sppkg" } }
<?xml version="1.0" encoding="utf-8"?> <Elements xmlns="http://schemas.microsoft.com/sharepoint/"> <CustomAction Title="SPFxApplicationCustomizer" Location="ClientSideExtension.ApplicationCustomizer" ClientSideComponentId="43833b44-df29-40bf-aec2-294dd435ee05"> </CustomAction> </Elements
{ "$schema": "../../node_modules/@microsoft/sp-module-interfaces/lib/manifestSchemas/jsonSchemas/clientSideComponentManifestSchema.json", "id": "43833b44-df29-40bf-aec2-294dd435ee05", "alias": "AppInsightsDemoSpFxExtensionApplication", "componentType": "Extension", "extensionType": "ApplicationCustomizer", "version": "*", // The "*" signifies that the version should be taken from the package.json "manifestVersion": 2, "safeWithCustomScriptDisabled": true }
import { override } from '@microsoft/decorators'; import { Log } from '@microsoft/sp-core-library'; import { BaseApplicationCustomizer, Placeholder } from '@microsoft/sp-application-base'; import { escape } from '@microsoft/sp-lodash-subset'; import * as strings from 'appInsightsDemoSpFxExtensionStrings'; const LOG_SOURCE: string = 'AppInsightsDemoSpFxExtensionApplicationCustomizer'; /** * If your command set uses the ClientSideComponentProperties JSON input, * it will be deserialized into the BaseExtension.properties object. * You can define an interface to describe it. */ export interface IAppInsightsDemoSpFxExtensionApplicationCustomizerProperties { Header: string; } /** A Custom Action which can be run during execution of a Client Side Application */ export default class AppInsightsDemoSpFxExtensionApplicationCustomizer extends BaseApplicationCustomizer<IAppInsightsDemoSpFxExtensionApplicationCustomizerProperties> { // Header reference private _headerPlaceholder: Placeholder; @override public onInit(): Promise<void> { Log.info(LOG_SOURCE, `Initialized ${strings.Title}`); return Promise.resolve<void>(); } @override public onRender(): void { let html: string = ''; html+= `<script type="text/javascript"> "var appInsights=window.appInsights||function(config){ function i(config){t[config]=function(){var i=arguments;t.queue.push(function(){t[config].apply(t,i)})}}var t={config:config},u=document,e=window,o="script",s="AuthenticatedUserContext",h="start",c="stop",l="Track",a=l+"Event",v=l+"Page",y=u.createElement(o),r,f;y.src=config.url||"https://az416426.vo.msecnd.net/scripts/a/ai.0.js";u.getElementsByTagName(o)[0].parentNode.appendChild(y);try{t.cookie=u.cookie}catch(p){}for(t.queue=[],t.version="1.0",r=["Event","Exception","Metric","PageView","Trace","Dependency"];r.length;)i("track"+r.pop());return i("set"+s),i("clear"+s),i(h+a),i(c+a),i(h+v),i(c+v),i("flush"),config.disableExceptionTracking||(r="onerror",i("_"+r),f=e[r],e[r]=function(config,i,u,e,o){var s=f&&f(config,i,u,e,o);return s!==!0&&t["_"+r](config,i,u,e,o),s}),t }({ instrumentationKey:"b4cf6d1c-5d38-48ce-ac4e-8a7802f2a1a0" }) window.appInsights=appInsights; appInsights.trackPageView(); </script>`; console.log('CustomHeader.onRender()'); // Handling header place holder if (!this._headerPlaceholder) { this._headerPlaceholder = this.context.placeholders.tryAttach( 'PageHeader', { onDispose: this._onDispose }); // The extension should not assume that the expected placeholder is available. if (!this._headerPlaceholder) { console.error('The expected placeholder was not found.'); return; } if (this.properties) { let headerString: string = this.properties.Header; if (!headerString) { headerString = '(Header property was not defined.)'; } if (this._headerPlaceholder.domElement) { this._headerPlaceholder.domElement.innerHTML = html; console.log('injected'); //alert('hello world'); } } } } private _onDispose(): void { console.log('[CustomHeader._onDispose] Disposed custom header.'); } }
However, when I upload the package I get in the App Catalog, the column Valid App Package = NO.
In case you have some time to help me, please find the attached .RAR, I guess the error is going to be something very simple. and yes, I am working on a developer tenant.
Jun 06 2017 09:32 PM
Hi Luis - what kind of tenant do you have - do you happen to know? The first drop will likely change a bunch, and we don't want people to be running it on production environments, so for now it requires a developer tenant (not a developer site collection, but a developer tenant). I believe the online documentation describes how to get one, but the link is here - https://dev.office.com/devprogram
Hopefully that unblocks you.
Jun 06 2017 09:44 PM
Hi Pat, thanks for the quick reply, yes its a developer tenant, I created this one when the first public preview of SPFx came out last year, so I dont think that should be the issue, but if there is a way to verify via powershell or something in the admin center, let me know and I can double check.
In the meantime, I also uploaded a .RAR file with all the code, in case anyone on the PG can take a quick look.
Thanks again
Jun 06 2017 10:02 PM
Hi Luis, does the package validate if you just run the Yeoman generator and package up the results of the default HelloWorld project without making any other changes?
Thanks!
-Jeremy Kelley
Jun 07 2017 04:21 AM
Hi Luis,
apparently issue was visible only when you reference elements.xml file in the package. If you remove the reference from package-solution.json, everything was working fine. There was no visible reason for why it failed, so suspecting some sort of an encoding issue.
I deleted existing elements.xml file and recreated that with needed elements and all works fine. I can't really explain this in 100% level, but that should fix the issue with you as well. If you still though have the original package (sppkg, which failed), can you zip that and also share it, so that we can truly do a repro for this, since want to understand what actually in detailed went wrong, so looping right engineers for this to avoid future issue.
Jun 07 2017 06:51 AM
Thanks Vesa for your reply, I will try your suggestion when I get home at night, in the meantime, please see the app package attached.
Jun 07 2017 09:27 AM
Jun 07 2017 11:55 AM
SolutionIssue was in the elements.xml file, but not in encoding. More obvious than that, but still hard to catch. App catalow actually has actually "unavailable apps" link, which provides details on the possible errors and it's typically really accurate.
If you open up the elements.xml file from the sharepoint/assets folder, you can see that the last Elements element is missing closing tag, like defined in above exception. Below is the original Elements.xml file content and you can see that we are missing final > closing. After adding that missing character there, it was all good for deployment.
<?xml version="1.0" encoding="utf-8"?> <Elements xmlns="http://schemas.microsoft.com/sharepoint/"> <CustomAction Title="SPFxApplicationCustomizer" Location="ClientSideExtension.ApplicationCustomizer" ClientSideComponentId="43833b44-df29-40bf-aec2-294dd435ee05"> </CustomAction> </Elements
So - completely logical reason, was just hard to spot.
Jun 07 2017 12:07 PM
Amazing, thanks a lot Vesa, sometimes just fresh eyes will spot the errors in minutes..
Jun 07 2017 12:09 PM
Jun 07 2017 12:39 PM
Jun 07 2017 01:34 PM
SP User voice suggestion created 🙂
Jun 07 2017 04:23 PM
Hi guys, I've just started getting something similar. I previously deployed a package happily to both our dev tenant catalog and also to our test tenant catalog. After making a few updates in the last 24/48 hrs I'm now no longer able to deploy the package to the test tenant catalog (I can still happily deploy the package to our dev tenant catalog).
In the test tenant catalog, it notes the following error:
Invalid SharePoint App package. Error: Unable to cast object of type 'Microsoft.SharePoint.ClientSideFramework.SPClientSideComponentMetadata' to type 'Microsoft.SharePoint.ClientSideComponent.SPClientSideComponentMetadata'.
A casting error between ClientSideFramework and ClientSideComponent.
Note: I haven't upgraded my current yo template to the latest 1.1.0 version. It's using the GA release version 1.0.0.
Any ideas?
Regards
Pete
Jun 07 2017 04:43 PM
Thanks for pointing that out Pete. We believe we have stopped the behaviour, and should work in a few minutes. Please let us know if it continues to be a problem.
Jun 07 2017 05:34 PM
Thanks Pat. That's working again now.
Jun 07 2017 08:03 PM
quick question.
What are the available placeholders? by debugging I could see that is PageHeader, PageFooter, and DialogContainer in other pages.
What I am trying to achieve is to INJECT App Insights tracking code into the page.
I dont have any error, but according to App Insights documentation, I should put the code before the </head> element.
I tried different ways, but I just can get any kind of stats on Applicaiton Insights, my best guess its becase the code is not before the end head tag, and therefore if the placeholder does not exist, then it will never work.
@override public onRender(): void { let html: string = ''; html+= `<script type="text/javascript"> "var appInsights=window.appInsights||function(config){ function i(config){t[config]=function(){var i=arguments;t.queue.push(function(){t[config].apply(t,i)})}}var t={config:config},u=document,e=window,o="script",s="AuthenticatedUserContext",h="start",c="stop",l="Track",a=l+"Event",v=l+"Page",y=u.createElement(o),r,f;y.src=config.url||"https://az416426.vo.msecnd.net/scripts/a/ai.0.js";u.getElementsByTagName(o)[0].parentNode.appendChild(y);try{t.cookie=u.cookie}catch(p){}for(t.queue=[],t.version="1.0",r=["Event","Exception","Metric","PageView","Trace","Dependency"];r.length;)i("track"+r.pop());return i("set"+s),i("clear"+s),i(h+a),i(c+a),i(h+v),i(c+v),i("flush"),config.disableExceptionTracking||(r="onerror",i("_"+r),f=e[r],e[r]=function(config,i,u,e,o){var s=f&&f(config,i,u,e,o);return s!==!0&&t["_"+r](config,i,u,e,o),s}),t }({ instrumentationKey:"b4cf6d1c-5d38-48ce-ac4e-8a7802f2a1a0", enableDebug: true, }) window.appInsights=appInsights; appInsights.trackPageView(); </script>`; console.log('CustomHeader.onRender()'); console.log('Available placeholders: ', this.context.placeholders.placeholderNames.join(', ')); // Handling header place holder if (!this._headerPlaceholder) { this._headerPlaceholder = this.context.placeholders.tryAttach( 'PageHeader', { onDispose: this._onDispose }); // The extension should not assume that the expected placeholder is available. if (!this._headerPlaceholder) { console.error('The expected placeholder was not found.'); return; } if (this.properties) { let headerString: string = this.properties.Header; if (!headerString) { headerString = '(Header property was not defined.)'; } if (this._headerPlaceholder.domElement) { this._headerPlaceholder.domElement.innerHTML = ` <div class="${styles.app}"> <div class="ms-bgColor-themeDark ms-fontColor-white ${styles.header}"> <i class="ms-Icon ms-Icon--Info" aria-hidden="true"></i> ${escape(headerString)}<p>hello world</p> <script type="text/javascript"> "var appInsights=window.appInsights||function(config){ function i(config){t[config]=function(){var i=arguments;t.queue.push(function(){t[config].apply(t,i)})}}var t={config:config},u=document,e=window,o="script",s="AuthenticatedUserContext",h="start",c="stop",l="Track",a=l+"Event",v=l+"Page",y=u.createElement(o),r,f;y.src=config.url||"https://az416426.vo.msecnd.net/scripts/a/ai.0.js";u.getElementsByTagName(o)[0].parentNode.appendChild(y);try{t.cookie=u.cookie}catch(p){}for(t.queue=[],t.version="1.0",r=["Event","Exception","Metric","PageView","Trace","Dependency"];r.length;)i("track"+r.pop());return i("set"+s),i("clear"+s),i(h+a),i(c+a),i(h+v),i(c+v),i("flush"),config.disableExceptionTracking||(r="onerror",i("_"+r),f=e[r],e[r]=function(config,i,u,e,o){var s=f&&f(config,i,u,e,o);return s!==!0&&t["_"+r](config,i,u,e,o),s}),t }({ instrumentationKey:"b4cf6d1c-5d38-48ce-ac4e-8a7802f2a1a0", enableDebug: true, }) window.appInsights=appInsights; appInsights.trackPageView(); </script> </div> </div>`; //this._headerPlaceholder.domElement.innerHTML = html; console.log('injected'); //alert('hello world'); } } } }
Jun 08 2017 05:59 AM
Jun 07 2017 11:55 AM
SolutionIssue was in the elements.xml file, but not in encoding. More obvious than that, but still hard to catch. App catalow actually has actually "unavailable apps" link, which provides details on the possible errors and it's typically really accurate.
If you open up the elements.xml file from the sharepoint/assets folder, you can see that the last Elements element is missing closing tag, like defined in above exception. Below is the original Elements.xml file content and you can see that we are missing final > closing. After adding that missing character there, it was all good for deployment.
<?xml version="1.0" encoding="utf-8"?> <Elements xmlns="http://schemas.microsoft.com/sharepoint/"> <CustomAction Title="SPFxApplicationCustomizer" Location="ClientSideExtension.ApplicationCustomizer" ClientSideComponentId="43833b44-df29-40bf-aec2-294dd435ee05"> </CustomAction> </Elements
So - completely logical reason, was just hard to spot.