Donnerstag, März 4, 2010, 04:50 PM
Ok, das Thema ist zwar schon alt, aber im Zusammenhang mit dem neuen SharePoint Client OM wieder aktuell: Silverlight Cross Domain Calls.Silverlight Applets, die auf dem SharePoint Server liegen und per Microsoft.SharePoint.Client auf z.B. Listen zugreifen, funktionieren eigentlich auf Anhieb. Man greift hier auf den aktuellen Kontext zu (sprich, die aktuelle URL):
context = SP.ClientContext.Current;
Wenn man aber eine Silverlight Anwendung nicht als Sandboxed Solution direkt in SharePoint lädt, wird man beim ersten Versuch zu debuggen einen "Security.Error" bekommen, denn man muss jetzt die URL zum Server explizit angeben:
context = new SP.ClientContext("http://devserver001/sites/Jonka/");
Exception {System.Security.SecurityException ... etc
Silverlight versucht hier wieder auf die Datei "clientaccesspolicy.xml" zuzugreifen, um die Berechtigungen zu prüfen - man befindet sich schließlich gerade auf der Domain "localhost".
Also wird clientaccesspolicy.xml mit folgendem Inhalt ganz einfach im root der entsprechenden SharePoint Application abgelegt (z.B. C:\inetpub\wwwroot\wss\VirtualDirectories\80)
<?xml version="1.0" encoding="utf-8" ?>
<access-policy>
<cross-domain-access>
<policy>
<allow-from http-request-headers="*">
<domain uri="http://localhost:53659"></domain>
</allow-from>
<grant-to>
<resource path="/" include-subpaths="true"></resource>
</grant-to>
</policy>
</cross-domain-access>
</access-policy>
Man kann auch <domain uri="*"> eintragen, dann gibt es keine Beschränkung der URL.
Die Datei ist natürlich nicht aufrufbar, da SharePoint das Dateisystem nicht nach außen öffnet. Zum Glück gibt es in SharePoint 2010 immer noch die beliebten "Managed Paths", um solche Inhalte zu veröffentlichen.
In der Central Administration unter "Application Management" - "Manage web applications" im Ribbon kann die Einstellung geöffnet werden:

Hier eine "Explicit inclusion" anlegen, und /clientaccesspolicy.xml als Pfad angeben:

Ein Klick auf "Add Path", und alles sollte funktionieren:

Dann kann auch von der Visual Studio Debug-Umgebung aus auf SharePoint 2010 Listen zugegriffen werden:

Quellen:
http://www.silverlighthack.com/post/200 ... -2%29.aspx
http://timheuer.com/blog/archive/2008/0 ... sense.aspx
| Permalink
| Related Link
Dienstag, März 2, 2010, 05:34 PM
Silverlight und SharePoint zu verbinden macht seit Version 2010 und dem Client Object Model (komisch, dass das nicht COM abgekürzt wird... *hust*) auf einmal richtig Sinn. Es gibt auch viele Arten, aus VisualStudio 2010 heraus eine Silverlight Applikation zu deployen. Ich hatte mich zunächst für ein PostBuild Deployment in das SharePoint ClientBin entschieden, mit dem Standard Silverlight-WebPart für die Anzeige.Leider cached der Internet-Explorer das XAP-File immer, so dass Änderungen nicht Sichtbar werden, und manuell den Cache zu leeren, ist viel zu umständlich. Zum Glück kann man den Cache auch per Commando-Zeile löschen, auch wenn der Befehl sich einem nicht sofort erschließt: (Gilt natürlich nur für den Internet Explorer)
RunDll32.exe InetCpl.cpl,ClearMyTracksByProcess 8
Im Post-Build event steht also folgendes:

copy SilverlightSharePointDemo.* "C:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\14\TEMPLATE\LAYOUTS\ClientBin"
RunDll32.exe InetCpl.cpl,ClearMyTracksByProcess 8
Danach kann man mit F6 das Projekt kompilieren und mit F5 im Browser neu laden. Alle Änderungen sollten dann sofort sichtbar sein.
Quelle:
http://blogs.techrepublic.com.com/windo ... ows/?p=574
Montag, März 1, 2010, 05:59 PM
So, endlich mein erster Blogeintrag zu SharePoint 2010:Für den Anfang wollte ich mit Visual Studio 2010 RC auf SharePoint 2010 Beta2 ein Visual WebPart deployen. Also habe ich VS 2010 RC Premium auf dem bestehenden SharePoint Server installiert. Leider musste ich feststellen, dass die Premium Version von Visual Studio nicht die SharePoint Vorlagen enthielt, obwohl sie eigentlich enthalten sein müssten. Aber für den Release Candidate braucht man offenbar in jedem Falle die Ultimate Variante:
Ich empfehle dafür den Link auf das ISO File, der sich auf der Download-Seite ganz klein versteckt:
http://download.microsoft.com/download/ ... Ult_RC.iso
Nachdem das installiert ist, kann man auch die SharePoint Vorlagen auswählen und eine Site des lokalen SharePoint zum Deployen und Debuggen angeben:

Leider bekam ich immer sofort oder beim Starten mit F5 einen der folgenden Fehler angezeigt:

"Could not load the Web.config configuration file. Check the file for any malformed XML elements, and try again. The following error occurred: The local SharePoint server is not available. Check that the server is running and connected to the SharePoint farm."
oder:

"Cannot connect to the SharePoint site: ... Make sure that the site URL is valid, that the SharePoint site is running on the local computer, and that the current user has the necessary permissions to access the site. [...]"
Unten in der Error List gibt es auch noch eine Meldung:

"Error occurred in deployment step 'Recycle IIS Application Pool': The local SharePoint server is not available. Check that the server is running and connected to the SharePoint farm."
Das ist natürlich nicht sehr aussagekräftig, denn natürlich läuft der lokale SharePoint und lässt sich auch lokal aufrufen. Also habe ich in einer WinForms-Anwendung versucht über das normale Objektmodell (SPSite) auf den Server zuzugreifen und siehe da, der Benutzer hat keine Datenbank-Berechtigungen!
In der neuen Kombination von Windows Server 2008 R2 und SQL Server 2008 R2 hat eben nicht mehr jeder lokale Admin auch gleichzeitig volle Datenbank-Berechtigungen - auch dann nicht, wenn alles auf einem System installiert ist. Auch hilft es offenbar nicht, den Benutzer als SharePoint Farm-Administrator einzutragen.
Das ist insofern komisch, da man hingegen Zugriff auf die SharePoint-Admin und -Search Datenbanken erhält. (Bug oder Feature?)
Gibt man seinem Benutzer, mit dem man am System angemeldet ist, Zugriff auf die entsprechende Content-DB (z.B. SharePoint_Content_1234567890) und die Config-DB (z.B. SharePoint_Config_1234567890) kann man auch wieder auf das Objektmodell zugreifen und das Debugging klappt.
Mittwoch, November 11, 2009, 05:22 PM
Heute hatte ich mal wieder das alte Problem, dass beim SQL Update eines gerade angelegten Datensatzes dieser nicht aktualisiert wurde, weil die automatisch vergebene ID der Auto-Increment Spalte sich nicht im bestehenden Objekt wiederfand.Normalerweise muss ich mich ja damit nicht rumärgern, weil ich entweder einen OR-Maper verwende, der das alles regelt, oder GUIDS verwende, die ich ja schon vorher kenne. Aber hier war es mal simples ADO.NET und Auto-IDs. Also wieder recherchieren...
Und damit ich das nicht nochmal raussuchen muss - falls ich es vergessen sollte - hier das einfachste Vorgehen in C# für ein INSERT mit darauffolgendem UPDATE mit ADO.NET auf einem SQL Server:
Um die eben erzeugte ID beim INSERT zu erhalten genügt es, ein SELECT scope_identity() an das INSERT Statement zu hängen.
z.B.:
INSERT INTO Customer (Name, LastName)
VALUES ('Max', 'Mustermann')
SELECT scope_identity()
Dann natürlich nicht mehr ExecuteNonQuery() ausführen, sondern ExecuteScalar():
object ret = command.ExecuteScalar();
int id = Convert.ToInt32(ret);
customer.Id = id;
Dann bekommt man die eben erzeugte ID in einem Command wieder zurück, und dann klappts auch mit dem Update.
Dienstag, September 22, 2009, 03:00 PM
Einen eigenen Custom Field Type zu erstellen ist eigentlich gar nicht so schwer, wenn man den richtigen Weg wählt. Das Thema ist zwar schon alt, und im Internet gibt es bereits einige Einträge zu diesem Thema, aber ich möchte hier einmal einen konkreten Anwendungsfall zeigen, bei dem solche eigenen Field Types wirklich Sinn machen.Ein solcher Custom Field Type kann nach dem Einbinden in jeder Liste oder Dokumentenbibliothek als zusätzlicher Spaltentyp eingebunden werden:

Der erste Versuch, das vielversprechende WSPBuilder Visual Studio Template zu verwenden, schlug leider fehl, weil die Daten meiner ListBox sich nicht speichern ließen... Der Manuelle Weg, auf Basis des Microsoft Beispielcodes, funktioniert allerdings auch zufriedenstellend. Auf den Komfort eines deploybaren WSP-Files muss man dann zunächst zwar verzichten, aber zum Entwickeln geht es dafür wesentlich schneller.
Im Folgenden wird gezeigt, wie man eine eigene Listen-Spalte definiert, die im Edit-Mode über eine Multi-Select-Box gefüllt wird, in der Ansicht aber für jede Auswahl ein entsprechendes Bild anzeigt. Die Piktogramme werden aus einer fest definierten SharePoint Image-Library geladen:

Und so wird's gemacht:
1. Leeres Visual Studio Projekt anlegen.
2. Der Einfachheit halber eine Ordnerstruktur anlegen
TEMPLATE
TEMPLATE\CONTROLTEMPLATES
TEMPLATE\XML
Und eine Referenz zu Microsoft.SharePoint hinzufügen, für die Verwendung der Basisklassen.

3. Die Assembly signieren
Der Public Key Token wird später für die XML-Felddefinition benötigt.
4. Die Felddefinion anlegen
Für die eigene Felddefinion wird eine Klasse benötigt, die von einem der SharePoint Feld-Basistypen ableitet. Im Folgenden wird von SPFieldMultiLine abgeleitet, um große Textmengen in diesem Feld speichern zu können. Das neue Feld hat den Namen Symbol - das Wort sollte also überall durch einen eigenen Namen ersetzt werden ;)
SymbolField.cs Listing:
using Microsoft.SharePoint; using Microsoft.SharePoint.WebControls; namespace SymbolFieldType { public class SymbolField : SPFieldMultiLineText { public SymbolField (SPFieldCollection fields, string fieldName) : base(fields, fieldName) { ; } public SymbolField (SPFieldCollection fields, string typeName, string displayName) : base(fields, typeName, displayName) { ; } public override Microsoft.SharePoint.WebControls.BaseFieldControl FieldRenderingControl { get { BaseFieldControl control = new SymbolFieldControl(); control.FieldName = this.InternalName; return control; } } public override string GetValidatedString (object value) { if (this.Required || value.ToString().Equals(string.Empty)) { throw new SPFieldValidationException("Symbols not assigned"); } return base.GetValidatedString(value); } } }
5. Die Control-Definion für den neuen Typ anlegen
Die Control-Definion bestimmt das Verhalten und das Aussehen des neuen Feldes in der Editier-Ansicht. Diese Klasse ist eigentlich die "Code-Behind" Klasse des ascx-Files.

Hier wird dem Anwender eine Multi-Select Listbox angezeigt.
SymbolFieldControl.cs Listing:
using System.Configuration; using System.Text; using System.Web.UI.WebControls; using Microsoft.SharePoint.WebControls; namespace SymbolFieldType { public class SymbolFieldControl : BaseFieldControl { #region [ Protected properties ] protected ListBox symbolListBox; #endregion #region [ Overridden methods ] protected override string DefaultTemplateName { get { return @"SymbolFieldControl"; } } public override object Value { get { this.EnsureChildControls(); return GetSelectedValues(this.symbolListBox); } set { this.EnsureChildControls(); string selectedItemsString = (string)this.ItemFieldValue; foreach (ListItem i in symbolListBox.Items) { if (i.Value.Length > 0 && selectedItemsString.Contains(i.Value)) { i.Selected = true; } } } } protected override void CreateChildControls () { if (this.Field == null || this.ControlMode == SPControlMode.Display) return; base.CreateChildControls(); this.symbolListBox = (ListBox)TemplateContainer.FindControl("symbolListBox"); if (this.symbolListBox == null) throw new ConfigurationException("SymbolFieldControl.ascx is corrupt."); if (!this.Page.IsPostBack) { this.symbolListBox.Items.AddRange(new ListItem[]{ new ListItem(string.Empty, null), new ListItem("Ätzend", "Aetzend.png"), new ListItem("Brandfördernd", "Brandfoerdernd.png"), new ListItem("Explosiv", "Explosiv.png"), new ListItem("Flammbar 1", "Flamm1.png"), new ListItem("Flammbar 2", "Flamm2.png"), new ListItem("Flammbar 3", "Flamm3.png"), new ListItem("Giftig", "Giftig.png"), new ListItem("Leicht entzündlich", "LeichtEntzuendlich.png"), new ListItem("Reizend", "Reizend.png"), }); this.symbolListBox.SelectionMode = ListSelectionMode.Multiple; } } #endregion #region [ Private methods ] private string GetSelectedValues (ListBox listBox) { StringBuilder selectedItems = new StringBuilder(); foreach (ListItem item in listBox.Items) { if (item.Selected) { selectedItems.Append("); selectedItems.Append(item.Value); selectedItems.Append("\">"); } } return selectedItems.ToString(); } #endregion } }
Die gewählten Einträge der ListBox werden gleich als String von HTML Image-Tags gespeichert, um später in der Listen-Ansicht nicht das Problem zu haben, dass man mit CAML die Elemente zerlegen und zusammenbauen muss *grusel*. Sicher gibt es auch schönere Ansätze, aber in diesem Fall funktioniert es auch so.
6. Das ascx-Control zum Bearbeiten des Feldes anlegen
Im Ordner TEMPLATE\CONTROLTEMPLATES eine leere ascx-Datei (ohne Code-Behind) anlegen, und folgenden Codeschnipsel einfügen:
<%@ Control Language="C#" Debug="true" %> <%@ Assembly Name="Microsoft.SharePoint, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %> <%@ Register TagPrefix="SharePoint" Assembly="Microsoft.SharePoint, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" Namespace="Microsoft.SharePoint.WebControls" %> <SharePoint:RenderingTemplate ID="SymbolFieldControl" runat="server"> <Template> <asp:ListBox ID="symbolListBox" runat="server" /> Template> SharePoint:RenderingTemplate>
Wenn man eigene Controls baut sollte man darauf achten, dass hier der Typ des ASP.NET controls dem Element entspricht, das man in der Field-Control Definition angegeben hat. Hier muss also zusammenpassen:
<asp:ListBox ID="symbolListBox" runat="server" />
und
protected ListBox symbolListBox;
7. Die XML-Felddefinion anlegen
im Ordner TEMPLATE\XML eine leere XML-Datei anlegen, und folgendes einfügen:
xml version="1.0" encoding="utf-8" ?> <FieldTypes> <FieldType> <Field Name="TypeName">SymbolSelectionField> <Field Name="ParentType">NoteField> <Field Name="SQLType">ntextField> <Field Name="TypeDisplayName">Danger signField> <Field Name="TypeShortDescription">Custom symbol columnField> <Field Name="Sortable">FALSEField> <Field Name="Filterable">FALSEField> <Field Name="UserCreatable">TRUEField> <Field Name="ShowInListCreate">TRUEField> <Field Name="ShowInSurveyCreate">TRUEField> <Field Name="ShowInDocumentLibraryCreate">TRUEField> <Field Name="ShowInColumnTemplateCreate">TRUEField> <Field Name="FieldTypeClass">SymbolFieldType.SymbolField, SymbolFieldType, Version=1.0.0.0, Culture=neutral, PublicKeyToken=!Hier den eigenen Token einsetzen!Field> <RenderPattern Name="DisplayPattern"> <Switch> <Expr> <Column/> Expr> <Case Value=""> Case> <Default> <Column/> Default> Switch> RenderPattern> FieldType> FieldTypes>
Der PublicKeyToken muss mit sn.exe -T MyCustomFieldType.dll aus der aktuellen Assembly ermittelt werden.
Erläuterungen:
"ParentType" gibt den internen zu verwendenen SharePoint Datentypen an. Note ist ein Text mit mehr als 255 Zeichen.
"SQLType" gibt den zu verwendenen Physikalischen Datentypen in der Datenbank an. Dies kann für den Note Typ nötig zu sein.
Die restelichen Field-Definitionen sollten selbsterklärend sein...
Wichtig ist natürlich der Abschnitt RenderPattern, in dem per CAML das Aussehen des Feldinhaltes in der Listenansicht und in der Detailansicht definiert wird. In diesem Beispiel wird der Inhalt einfach nur 1:1 ausgegeben, denn er ist ja bereits richtig formatiert:
<Default> <Column/> Default>
8. Deployment
Ohne WSP-Datei, muss alles per Hand installiert werden. Das geht jedoch wesentlich schneller!
- Die kompilierte DLL des Projektes kommt in den GAC auf dem Webserver. Einfach mit dem Explorer hineinkopieren.
- Die ascx-Datei kopiert man in den Ordner ...\12\TEMPLATE\CONTROLTEMPLATES
- Und die XML-Datei kopiert man in den Ordner ...\12\TEMPLATE\XML
Wenn man jetzt im IIS den entsprechenden Application-Pool aktualisiert (recycle), sollte der neue Feld-Typ auch schon verfügbar sein!
Das ganze muss man bei einer Server-Farm natürlich für jeden FrontendWebServer machen. Dafür kann man sich aber eine kleine Batch-Datei schreiben...
Um den Feld-Typen zu deinstallieren, genügt es, die Assembly aus dem GAC zu entfernen und die beiden Dateien im Filesystem zu löschen.
Quellen:
http://wspbuilder.codeplex.com/Release/ ... seId=25962
Weiter

Calendar



