1: using System;
2: using Microsoft.SharePoint;
3: using Microsoft.SharePoint.WebControls;
4: using System.Web.UI.WebControls;
5: using System.Collections;
6: using System.Web.UI;
7: using System.Data;
8: using Microsoft.SharePoint.Administration;
9: using System.Collections.Generic;
10: using System.Linq;
11: using COB.SharePoint.Utilities.FeatureUpgradeKit.Entities;
12: using COB.SharePoint.Utilities.FeatureUpgradeKit.Core;
13:
14: namespace COB.SharePoint.Utilities.FeatureUpgradeKit
15: {
16: /// <summary>
17: /// Provides an administration page for upgrading Features in SharePoint.
18: /// </summary>
19: /// <created by="Chris O'Brien" date="09 July 2010" />
20: public partial class CentralAdminFeatureUpgrade : LayoutsPageBase
21: {
22: #region -- Fields and child classes --
23:
24: private Hashtable fields = new Hashtable();
25: private DataTable dtFeatures = null;
26: private const string NeedUpgradeValue = "NeedUpgrade";
27: public const string UpgradeCheckBoxId = "chkUpgrade";
28:
29: private class FeatureFields
30: {
31: public const string DisplayName = "DisplayName";
32: public const string Version = "Version";
33: public const string Parent = "Parent";
34: public const string DoUpgrade = "DoUpgrade";
35: public const string FeatureID = "FeatureID";
36: public const string FeatureScope = "Scope";
37: public const string Identifiers = "Identifiers";
38: }
39:
40: private class GridHeaders
41: {
42: public const string DisplayName = "Feature name";
43: public const string Version = "Current version";
44: public const string Parent = "Parent";
45: public const string DoUpgrade = "Upgrade?";
46: public const string FeatureID = "Feature ID";
47: public const string FeatureScope = "Scope";
48: public const string Identifiers = "Identifiers";
49: }
50:
51: #endregion
52:
53: #region -- Page event handlers --
54:
55: protected override void OnInit(EventArgs e)
56: {
57: // initialise SPGridView etc..
58: addColumns();
59: grdFeatures.AllowSorting = false;
60:
61: topOKButton.Visible = false;
62: base.OnInit(e);
63: }
64:
65: protected override void OnLoad(EventArgs e)
66: {
67: // any postback on this page is caused by controls related to querying Features/working with grid, so we'll rebind data on any postback..
68: if (Page.IsPostBack)
69: {
70: populateFeaturesTable();
71: bindData(dtFeatures);
72: }
73:
74: base.OnLoad(e);
75: }
76:
77: protected void searchButton_Click(object sender, EventArgs e)
78: {
79: if (dtFeatures != null)
80: {
81: topOKButton.Visible = (dtFeatures.Rows.Count > 0 && rblUpgradeOnly.SelectedValue == NeedUpgradeValue);
82: pnlNoEntries.Visible = (dtFeatures.Rows.Count == 0);
83: pnlUpgradeFailure.Visible = false;
84: pnlUpgradeSuccess.Visible = false;
85: }
86: }
87:
88: protected void okButton_Click(object sender, EventArgs e)
89: {
90: clearMessages();
91:
92: List<FeatureDetails> upgradeIdentifiers = new List<FeatureDetails>();
93: foreach (SPGridViewRow row in grdFeatures.Rows)
94: {
95: Control c = row.FindControl(UpgradeCheckBoxId);
96: CheckBox chk = c as CheckBox;
97: if ((chk != null) && (chk.Checked))
98: {
99: upgradeIdentifiers.Add(FeatureDetails.CreateFromString(grdFeatures.DataKeys[row.RowIndex].Value.ToString()));
100: }
101: }
102:
103: // upgrade selected Features and display results..
104: SPSecurity.RunWithElevatedPrivileges(delegate() {
105: Dictionary<FeatureDetails, IEnumerable<Exception>> upgradeResults = FeatureManager.UpgradeFeatures(upgradeIdentifiers);
106: presentResultMessages(upgradeResults);
107: });
108:
109: // now re-run query to update grid..
110: populateFeaturesTable();
111: bindData(dtFeatures);
112:
113: if (dtFeatures.Rows.Count == 0)
114: {
115: pnlNoEntries.Visible = false;
116: topOKButton.Visible = false;
117: }
118: }
119:
120: #endregion
121:
122: #region -- UI handling --
123:
124: private void presentResultMessages(Dictionary<FeatureDetails, IEnumerable<Exception>> upgradeResults)
125: {
126: int errorCount = 0;
127: foreach (KeyValuePair<FeatureDetails, IEnumerable<Exception>> kvp in upgradeResults)
128: {
129: List<Exception> exceptions = null;
130: if (kvp.Value != null)
131: {
132: exceptions = kvp.Value.ToList();
133: }
134:
135: if (exceptions != null && exceptions.Count > 0)
136: {
137: pnlUpgradeFailure.Visible = true;
138: if (errorCount > 0)
139: {
140: lblErrors.Text += "<br />";
141: }
142: lblErrors.Text += string.Format("Feature '{0}' with parent '{1}' failed with the following errors:<br /><br />",
143: kvp.Key.FeatureName, kvp.Key.ParentString);
144: foreach (Exception exception in exceptions)
145: {
146: lblErrors.Text += string.Format(" - {0}<br />", exception.ToString());
147: errorCount += exceptions.Count;
148: }
149: }
150: else
151: {
152: pnlUpgradeSuccess.Visible = true;
153: lblSuccesses.Text += string.Format("Feature '{0}' with parent '{1}' upgraded successfully.<br />",
154: kvp.Key.FeatureName, kvp.Key.ParentString);
155: }
156: }
157: }
158:
159: private void clearMessages()
160: {
161: lblErrors.Text = string.Empty;
162: lblSuccesses.Text = string.Empty;
163: lblResults.Text = string.Empty;
164: }
165:
166: private void bindData(DataTable dtFeatures)
167: {
168: // assign default sort expression..
169: DataView sortedView = new DataView(dtFeatures);
170: sortedView.Sort = FeatureFields.DisplayName + " ASC";
171:
172: // add columns to grid..
173: grdFeatures.Columns.Clear();
174:
175: foreach (DictionaryEntry de in fields)
176: {
177: bool visibleField = (de.Key.ToString() != GridHeaders.Identifiers);
178: addBoundField(de.Key.ToString(), de.Value.ToString(), visibleField);
179: }
180:
181: if (rblUpgradeOnly.SelectedValue == NeedUpgradeValue)
182: {
183: // add checkbox column..
184: addUpgradeCheckBox(grdFeatures);
185: }
186:
187: grdFeatures.DataKeyNames = new string[] { FeatureFields.Identifiers };
188: grdFeatures.DataSource = sortedView;
189: grdFeatures.DataBind();
190: }
191:
192: private static void addUpgradeCheckBox(SPGridView gridView)
193: {
194: TemplateField upgradeField = new TemplateField
195: {
196: HeaderText = GridHeaders.DoUpgrade,
197: ItemTemplate = new UpgradeCheckBoxGridviewTemplate()
198: };
199:
200: gridView.Columns.Add(upgradeField);
201: }
202:
203: private void addBoundField(string headerText, string dataField, bool visibleField)
204: {
205: SPBoundField userField = new SPBoundField();
206: userField.HeaderText = headerText;
207: userField.DataField = dataField;
208: userField.SortExpression = headerText;
209: userField.Visible = visibleField;
210: grdFeatures.Columns.Add(userField);
211: }
212:
213: private static Control findControlRecursive(Control Root, string Id)
214: {
215: if (Root.ID == Id)
216: return Root;
217:
218: foreach (Control Ctl in Root.Controls)
219: {
220: Control FoundCtl = findControlRecursive(Ctl, Id);
221: if (FoundCtl != null)
222: return FoundCtl;
223: }
224:
225: return null;
226: }
227:
228:
229: #endregion
230:
231: #region -- Feature handling --
232:
233: private void populateFeaturesTable()
234: {
235: string siteUrl = SPContext.Current.Site.Url;
236: DropDownList ddlScopes = (DropDownList)findControlRecursive(scopeSection, "ddlScopes");
237: RadioButtonList rblUpgradeOnly = (RadioButtonList)findControlRecursive(featureFilterSection, "rblUpgradeOnly");
238: bool upgradeOnly = (rblUpgradeOnly.SelectedValue == NeedUpgradeValue);
239: SPFeatureScope scope = (SPFeatureScope)Enum.Parse(typeof(SPFeatureScope), ddlScopes.SelectedValue);
240: SPFeatureQueryResultCollection featuresForUpgrade = null;
241:
242: switch (scope)
243: {
244: case SPFeatureScope.Farm:
245: featuresForUpgrade = SPWebService.AdministrationService.QueryFeatures(scope, upgradeOnly);
246: break;
247: case SPFeatureScope.WebApplication:
248: featuresForUpgrade = SPWebService.QueryFeaturesInAllWebServices(scope, upgradeOnly);
249: break;
250: case SPFeatureScope.Site:
251: featuresForUpgrade = webAppSelector.CurrentItem.QueryFeatures(scope, upgradeOnly);
252: break;
253: case SPFeatureScope.Web:
254: using (SPSite selectedSite = new SPSite(siteCollectionSelector.CurrentItem.Url))
255: {
256: featuresForUpgrade = selectedSite.QueryFeatures(scope, upgradeOnly);
257: }
258: break;
259: default:
260: throw new NotImplementedException(string.Format("Cannot use this page to upgrade Features at scope '{0}'!", scope));
261: }
262:
263: dtFeatures = getDataTable(featuresForUpgrade);
264: }
265:
266: private DataTable getDataTable(SPFeatureQueryResultCollection featuresForUpgrade)
267: {
268: DataTable dtEntries = new DataTable("FeatureQueryResult");
269: dtEntries.Columns.Add(new DataColumn(FeatureFields.DisplayName));
270: dtEntries.Columns.Add(new DataColumn(FeatureFields.Parent));
271: dtEntries.Columns.Add(new DataColumn(FeatureFields.Version));
272: dtEntries.Columns.Add(new DataColumn(FeatureFields.FeatureID));
273: dtEntries.Columns.Add(new DataColumn(FeatureFields.FeatureScope));
274: dtEntries.Columns.Add(new DataColumn(FeatureFields.Identifiers));
275:
276: foreach (SPFeature feature in featuresForUpgrade)
277: {
278: string parent = FeatureManager.GetFeatureParent(feature);
279: DataRow dr = dtEntries.NewRow();
280: dr[FeatureFields.DisplayName] = feature.Definition.DisplayName;
281: dr[FeatureFields.Parent] = parent;
282: dr[FeatureFields.Version] = feature.Version;
283: dr[FeatureFields.FeatureID] = feature.DefinitionId;
284: dr[FeatureFields.FeatureScope] = feature.Definition.Scope;
285: dr[FeatureFields.Identifiers] = new FeatureDetails()
286: {
287: FeatureScope = feature.Definition.Scope,
288: FeatureID = feature.DefinitionId,
289: ParentID = new Guid(FeatureManager.GetFeatureParentId(feature).ToString()),
290: GrandParentID = new Guid(FeatureManager.GetFeatureGrandParentId(feature).ToString()),
291: FeatureName = feature.Definition.DisplayName,
292: ParentString = parent
293: }.ToString();
294:
295: dtEntries.Rows.Add(dr);
296: }
297:
298: return dtEntries;
299: }
300:
301: #endregion
302:
303: #region -- Misc helpers --
304:
305: private void addColumns()
306: {
307: fields.Add(GridHeaders.DisplayName, FeatureFields.DisplayName);
308: fields.Add(GridHeaders.Version, FeatureFields.Version);
309: fields.Add(GridHeaders.Parent, FeatureFields.Parent);
310: fields.Add(GridHeaders.FeatureID, FeatureFields.FeatureID);
311: fields.Add(GridHeaders.FeatureScope, FeatureFields.FeatureScope);
312: fields.Add(GridHeaders.Identifiers, FeatureFields.Identifiers);
313: }
314:
315:
316:
317: #endregion
318: }
319: }