SharePoint 2013 Apps: SecurityToken bei Remote Apps

Wenn man in Visual Studio 2012 eine neue cloud-basierte App (auto-hosted oder provider-hosted) anlegt und einfach nur bereitstellt, funktioniert beim ersten Aufruf der App im Browser alles tadellos. Jeder weitere Aufruf z.B. durch eigene Links innerhalb der App oder auch durch einen simplen Button-Klick verursachen jedoch einen Fehler: The parameter ‚token‘ cannot be a null or empty string. Im Browser sieht man die berüchtigte ASP.NET Fehlerseite:

Wie man sieht, entsteht der Fehler beim Versuch ein SecurityToken zu finden, das für den Zugriff von der App aus auf Daten in SharePoint benötigt wird. Visual Studio erzeugt beim Anlegen eines neuen App-Projekts automatisch eine Datei TokenHelper.cs, die eigentlich alles notwendige beinhaltet. Beim Analysieren dieser Datei stellt man dann aber fest, daß dort versucht wird auf Request-Parameter zuzugreifen, die zwar beim ersten Aufruf aus SharePoint gesetzt werden, aber bei jedem weiteren Request dann fehlen.

Man muß sich also selbst darum kümmern diese Werte zwischenzuspeichern. Das kann man mit den bewährten Mitteln von ASP.NET an verschiedenen Stellen machen. Innerhalb einer Seite z.B. im ViewState oder in serverseitigen hidden-Controls. Aber auch seitenübergreifend in der Session. Natürlich sind auch ganz andere Orte denkbar, wie z.B. das Speichern in einer Datenbank.

Eigentlich reicht es das sogenannte Context Token (ein String) zu speichern. Wenn man schon dabei ist, lohnt es sich aber auch gleich die HostUrl mit zu speichern, damit sie in allen weiteren Seitenaufrufen auch wirklich zur Verfügung steht. Dadurch funktioniert auch alles, wenn man vergißt diese Url in einem eigenen Link weiterzugeben.

Ich habe mich dazu entschieden die Werte in der Session abzulegen, weil ich sie dann innerhalb des gesamten AppWebs verwenden kann. Dazu habe ich eine eigene Methode GetContext erstellt, die den passenden ClientContext zurückgibt. Die Methode habe ich als statische Methode einfach zusätzlich in die TokenHelper-Klasse eingebaut. Immer wen man irgendwo einen ClientContext benötigt, kann man dann auf diese Methode zugreifen (anstelle der sonst verwendeten TokenHelper.GetClientContextWithContextToken. Der Methode muß nur der aktuelle HttpContext übergeben werden, der in jeder Seite über HttpContext.Current erreichbar ist. So sieht die Methode aus:

public static ClientContext GetContext(HttpContext httpContext) {
 
string token = httpContext.Session["myToken"] as string;
  string hostUrl = httpContext.Session["myHostUrl"] as string;
  if (token == null || hostUrl == null) {
    token = TokenHelper.GetContextTokenFromRequest(httpContext.Request);
    hostUrl = httpContext.Request["SPHostUrl"];
    httpContext.Session["myToken"] = token;
    httpContext.Session["myHostUrl"] = hostUrl;
  }
  return TokenHelper.GetClientContextWithContextToken(hostUrl, token, httpContext.Request.Url.Authority);
}

Kommentar verfassen

Trage deine Daten unten ein oder klicke ein Icon um dich einzuloggen:

WordPress.com-Logo

Du kommentierst mit Deinem WordPress.com-Konto. Abmelden / Ändern )

Twitter-Bild

Du kommentierst mit Deinem Twitter-Konto. Abmelden / Ändern )

Facebook-Foto

Du kommentierst mit Deinem Facebook-Konto. Abmelden / Ändern )

Google+ Foto

Du kommentierst mit Deinem Google+-Konto. Abmelden / Ändern )

Verbinde mit %s