SOLVED

Invalid Package - Sharepoint Framework Extensions

Deleted
Not applicable

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"
}
}
Elements.xml on the assets folder
 
 
<?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
 
manifest.json
 
 
{
"$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
}
and finally my extension code
 
 
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.

 

1.png2.png

 

 

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.

 

 

16 Replies

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.

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.

 

https://wetransfer.com/downloads/705a938fc611eb1352731914c1fd80b920170607043607/20c0cf80a35d6ff8aaa1...

 

Thanks again

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

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.

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.

 

 

didnt try it, but I will check also with Vesa suggestion
best response
Solution

Issue 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.

 

apps-sharepoint.jpg

 

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. 

Amazing, thanks a lot Vesa, sometimes just fresh eyes will spot the errors in minutes..

btw, I guess gulp serve only compiles/transpiles typescript and it doesnt check xml files thats why the error never came up, any idea how to avoid this in the future (my question is from the tooling perspective), it would be nice to see a warning somewhere.

Maybe a gulp custom task, that checks xml formatting at least?
Good suggestion around the schema validation improvement. Thx Luis.

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

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.

Thanks Pat.  That's working again now.

 

@Vesa Juvonen

 

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');
        }
      }
    }
  }
Hi Luis,
We have header and footer placeholders to start with. I, unfortunately, haven't had time to test app insights scenario yet, so not sure how it should be setup. Would though suggest that we get this discussion moved under a different topic in this developer space so that the title is accurate enough for other people looking to solve similar things.
1 best response

Accepted Solutions
best response
Solution

Issue 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.

 

apps-sharepoint.jpg

 

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. 

View solution in original post