Custom Action con codice per SharePoint
In SharePoint 2007 (WSS3 - MOSS) è possibile generare la url di una custom action tramite codice C#.
In questo esempio genero una action nel formato
dove estraggo anche il guid delle vista non disponibile nelle normali custom action costruite con il solo xml.
La custom action chiama la pagina ViewInfo.aspx che visualizza alcune informazioni relative alla vista.
Le informazioni sono:
L'importante è estendere la classe da System.Web.UI.WebControls.WebControl, sovrascrivere il metodo CreateChildControls e aggiungere uno o più oggetti MenuItemTemplate.
Il passo successivo è costruire una feature, e per far questo servono i file feature.xml ed elements.xml:
dove ho sostituito xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxx con un nuovo guid e i parametri ControlAssembly con la firma dell'assembly e ControlClass il nome della classe che implementa la custon action.
Ho aggiunto anche un esempio di feature, agganciata al menu contestuale dell'item (EditControlBlock), fatta solo tramite xml (che punta ad una pagina inesistente). Questo per evidenziare che:
Adesso che abbiamo tutti i file (nella stessa directory) non ci resta che creare una solution per il deploy.
Per far questo servono i file manifest.xml, solution.ddf e makesolution.bat.
Anche qui va generato un nuovo guig per la solution e va sostituita la firma dell'assemly e il namespace.
Per installare la solution
Infine attiva la feature sulla site collection.
In questo esempio genero una action nel formato
Text
http://sharepoint/site/site/_layouts/Sgart/ViewInfo.aspx?ListID=<guid>&ViewID=<guid>&login=<loginName>&t=<actualTime>
La custom action chiama la pagina ViewInfo.aspx che visualizza alcune informazioni relative alla vista.
Le informazioni sono:
- elenco dei campi (SPView.ViewField)
- query (SPView.Query)
- schema (SPView.Schema) della vista
C#: SgartCustomAction.cs
using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.SharePoint;
using Microsoft.SharePoint.WebControls;
namespace Sgart
{
public class MyCustomAction : System.Web.UI.WebControls.WebControl
{
protected override void CreateChildControls()
{
Guid listId = SPContext.Current.ListId;
Guid viewId = SPContext.Current.ViewContext.ViewId;
SPWeb web = SPContext.Current.Web;
string url = string.Format(
"{0}/_layouts/Sgart/ViewInfo.aspx?ListID={1}&ViewID={2}&login={3}&t={4}"
, web.Url
, Context.Server.UrlEncode( listId.ToString("B"))
, Context.Server.UrlEncode(viewId.ToString("B"))
, Context.Server.UrlEncode(web.CurrentUser.LoginName)
, Context.Server.UrlEncode(DateTime.Now.ToString("s"))
);
MenuItemTemplate mi = new MenuItemTemplate();
mi.Text = "Sgart Custom Action";
mi.Description = "Show field and query";
mi.ClientOnClickNavigateUrl = url;
mi.Sequence = 1001;
this.Controls.Add(mi);
this.ChildControlsCreated = true;
}
}
}
L'importante è estendere la classe da System.Web.UI.WebControls.WebControl, sovrascrivere il metodo CreateChildControls e aggiungere uno o più oggetti MenuItemTemplate.
Il passo successivo è costruire una feature, e per far questo servono i file feature.xml ed elements.xml:
XML: feature.xml
<?xml version="1.0" encoding="utf-8" ?>
<Feature Id="xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxx"
Title="Sgart Custom Action"
Description="Example of custom action by code"
Version="1.0.0.0"
Scope="Site"
Hidden="FALSE"
xmlns="http://schemas.microsoft.com/sharepoint/">
<ElementManifests>
<ElementManifest Location="elements.xml"/>
</ElementManifests>
</Feature>
XML: elements.xml
<Elements xmlns="http://schemas.microsoft.com/sharepoint/">
<CustomAction
Id="SgartCACode"
Location="Microsoft.SharePoint.StandardMenu"
GroupId="SettingsMenu"
RegistrationType="ContentType"
RegistrationId="0x"
ControlAssembly="Sgart.Contacts, Version=1.0.0.0, Culture=neutral, PublicKeyToken=b7af4e5276707a76"
ControlClass="Sgart.MyCustomAction"
/>
<CustomAction
Id="SgartECBTest"
Location="EditControlBlock"
RegistrationType="List"
RegistrationId="101"
Title="Example of context action"
Description="not show"
>
<UrlAction Url="~site/_layouts/Sgart/MyCustomActionTest.aspx?ID={ItemId}&List={ListId}"/>
</CustomAction>
</Elements>
Ho aggiunto anche un esempio di feature, agganciata al menu contestuale dell'item (EditControlBlock), fatta solo tramite xml (che punta ad una pagina inesistente). Questo per evidenziare che:
Non è possibile generare un item del menù contestuale tramite codice in quanto viene renderizzato lato client tramite JavaScript
Delle due custom action, la prima è nel menu Settings di tutte le liste (ContentType 0x), mentre la seconda compare solo sulle document library (List 101).XML: ViewInfo.aspx
<%@ Assembly Name="Microsoft.SharePoint, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c"%>
<%@Page Language="C#" MasterPageFile="~/_layouts/application.master" Inherits="Microsoft.SharePoint.WebControls.LayoutsPageBase" %>
<%@ Register Tagprefix="SharePoint" Namespace="Microsoft.SharePoint.WebControls" Assembly="Microsoft.SharePoint, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>
<%@ Import Namespace="Microsoft.SharePoint" %>
<%@ Import Namespace="System.Data" %>
<script runat="server">
protected override void OnLoad(EventArgs e)
{
Guid listId = new Guid(Request.QueryString["ListId"]);
Guid viewId = new Guid(Request.QueryString["ViewId"]);
SPWeb web = this.Web;
SPList list = web.Lists[listId];
SPView view = list.Views[viewId];
lblTitle.Text = view.Title;
lblTitle2.Text = view.ServerRelativeUrl;
System.Data.DataTable tblFields = new DataTable();
System.Data.DataColumn dcPos = tblFields.Columns.Add("Pos", typeof(System.Int32));
System.Data.DataColumn dcTitle = tblFields.Columns.Add("Title", typeof(System.String));
System.Data.DataColumn dcName = tblFields.Columns.Add("InternalName", typeof(System.String));
System.Data.DataColumn dcType = tblFields.Columns.Add("Type", typeof(System.String));
int i = 1;
SPFieldCollection fields = list.Fields;
DataRowCollection rows = tblFields.Rows;
foreach (string fldName in view.ViewFields)
{
SPField fld = fields.GetFieldByInternalName(fldName);
DataRow r = tblFields.NewRow();
r[dcPos] = i++;
r[dcTitle] = fld.Title;
r[dcName] = fld.InternalName;
r[dcType] = fld.TypeDisplayName;
rows.Add(r);
}
gvFields.DataSource = tblFields;
gvFields.DataBind();
txtQuery.Text = Context.Server.HtmlEncode(view.Query);
txtSchema.Text = Context.Server.HtmlEncode(view.SchemaXml);
}
</script>
<asp:Content ID="Main" runat="server" ContentPlaceHolderID="PlaceHolderMain">
<h3>Fields</h3>
<SharePoint:SPGridView ID="gvFields" runat="server" AutoGenerateColumns="false">
<Columns>
<SharePoint:SPBoundField DataField="Pos" HeaderText="Pos" />
<SharePoint:SPBoundField DataField="Title" HeaderText="Display Name" />
<SharePoint:SPBoundField DataField="InternalName" HeaderText="Internal Name" />
<SharePoint:SPBoundField DataField="Type" HeaderText="Type" />
</Columns>
</SharePoint:SPGridView>
<br />
<h3>Query</h3>
<asp:label ID="txtQuery" runat="server" />
<br />
<h3>Schema</h3>
<asp:label ID="txtSchema" runat="server" />
</asp:Content>
<asp:Content ID="PageTitle" runat="server"
ContentPlaceHolderID="PlaceHolderPageTitle">
More info on view
</asp:Content>
<asp:Content ID="PageTitleInTitleArea" runat="server"
ContentPlaceHolderID="PlaceHolderPageTitleInTitleArea">
View info: <asp:Label ID="lblTitle" runat="server" />
<h6>Url: <asp:Label ID="lblTitle2" runat="server" /></h6>
</asp:Content>
Adesso che abbiamo tutti i file (nella stessa directory) non ci resta che creare una solution per il deploy.
Per far questo servono i file manifest.xml, solution.ddf e makesolution.bat.
C#: manifext.xml
<?xml version="1.0" encoding="utf-8" ?>
<Solution SolutionId="ssssss-ssss-ssss-ssss-ssssssssss"
xmlns="http://schemas.microsoft.com/sharepoint/">
<FeatureManifests>
<FeatureManifest Location="SgartCustomAction\Feature.xml" />
</FeatureManifests>
<TemplateFiles>
<TemplateFile Location="LAYOUTS\Sgart\ViewInfo.aspx"/>
</TemplateFiles>
<Assemblies>
<Assembly Location="Sgart.Contacts.dll"
DeploymentTarget="GlobalAssemblyCache" >
<SafeControls>
<SafeControl Assembly="Sgart.WebControls, Version=1.0.0.0, Culture=neutral, PublicKeyToken=b7af4e5276707a76"
Namespace="Sgart.WebControls"
TypeName="*"
Safe="True" />
</SafeControls>
</Assembly>
</Assemblies>
</Solution>
Text: solution.ddf
.OPTION EXPLICIT ; Generate errors
.Set CabinetNameTemplate=SgartCusomAction.wsp
.Set DiskDirectoryTemplate=CDROM ; All cabinets go in a single directory
.Set CompressionType=MSZIP;** All files are compressed in cabinet files
.Set UniqueFiles="ON"
.Set Cabinet=on
.Set DiskDirectory1=.
.Set DestinationDir=
manifest.xml
Bin\Debug\SgartCustomAction.dll
.Set DestinationDir=SgartCustomAction
feature.xml
elements.xml
.Set DestinationDir=LAYOUTS\Sgart
ViewInfo.aspx
DOS / Batch file: makesolution.bat
makecab.exe /F solution.ddf
DOS / Batch file
stsadm -o installfeature -filename SgartCustomAction\feature.xml -force
REM stsadm -o -uninstallfeature -filename SgartCustomAction\feature.xml -force