Microsoft provides a sophisticated API/Object Model for programmatic access to the SharePoint from .NET custom code.
The above code leaks memory and resources, since the developer is allocating a site and web instance and never disposing of the objects. A better approach is the following code:
Since we’re avoiding passing around references to these potentially leaky objects, how should developers write code?
The answer is to use delegates. The following code is a handy helper class that encapsulates the use of SPSite and SPWeb objects, and executes custom code via delegates:
1: /// <summary>
2: /// Helper class to prevent memory leakage in SharePoint Object Model calls.
3: /// </summary>
4: public static class SPHelper
5: {
6: #region Methods
7:
8: /// <summary>
9: /// Get a SPSite reference for a given <paramref name="url">site URL</paramref> and execute
10: /// a given <paramref name="action">Action</paramref>.
11: /// </summary>
12: /// <param name="url">Site Url.</param>
13: /// <param name="action">Action delegate.</param>
14: public static void GetSite(string url, Action<SPSite> action)
15: {
16: if (String.IsNullOrEmpty(url))
17: throw new ArgumentNullException("url");
18: if (null == action)
19: throw new ArgumentNullException("action");
20: using (var site = new SPSite(url))
21: action(site);
22: }
23:
24: /// <summary>
25: /// Get an SPSite and SPWeb reference for a given <paramref name="url">site URL</paramref> and execute
26: /// a given <paramref name="action">Action</paramref>.
27: /// </summary>
28: /// <param name="url">Web Url.</param>
29: /// <param name="action">Action delegate.</param>
30: public static void GetWeb(string url, Action<SPSite, SPWeb> action)
31: {
32: if (String.IsNullOrEmpty(url))
33: throw new ArgumentNullException("url");
34: if (null == action)
35: throw new ArgumentNullException("action");
36: using (var site = new SPSite(url))
37: {
38: using (var web = site.OpenWeb())
39: {
40: if (null == web)
41: throw new SPException("Failed to open web");
42: action(site, web);
43: }
44: }
45: }
46:
47: /// <summary>
48: /// Get an SPSite and SPWeb (root) reference for a given <paramref name="url">site URL</paramref> and execute
49: /// a given <paramref name="action">Action</paramref>.
50: /// </summary>
51: /// <param name="url">Site Url.</param>
52: /// <param name="action">Action delegate.</param>
53: public static void GetRootWeb(string url, Action<SPSite, SPWeb> action)
54: {
55: if (String.IsNullOrEmpty(url))
56: throw new ArgumentNullException("url");
57: if (null == action)
58: throw new ArgumentNullException("action");
59: using (var site = new SPSite(url))
60: {
61: using (var web = site.RootWeb)
62: {
63: action(site, web);
64: }
65: }
66: }
67:
68: /// <summary>
69: /// Get an SPSite and SPWeb reference for a given <paramref name="url">site URL</paramref> and
70: /// <paramref name="username"/> and execute
71: /// a given <paramref name="action">Action</paramref>.
72: /// </summary>
73: /// <remarks>Username must be a user in the site.</remarks>
74: /// <param name="url">Site Url.</param>
75: /// <param name="username">Username with access to the web.</param>
76: /// <param name="action">Action delegate.</param>
77: public static void GetSecureWeb(string url, string username, Action<SPSite, SPWeb, SPUser> action)
78: {
79: if (String.IsNullOrEmpty(url))
80: throw new ArgumentNullException("url");
81: if (String.IsNullOrEmpty(username))
82: throw new ArgumentNullException("username");
83: if (null == action)
84: throw new ArgumentNullException("action");
85: // Open the regular web first.
86: using (var site = new SPSite(url))
87: {
88: using (var web = site.RootWeb)
89: {
90: // See if user is registered with the root web.
91: var user = web.AllUsers[username];
92: if (null == user)
93: throw new SPException("No user found");
94: // Open the secure site.
95: using (var secureSite = new SPSite(url, user.UserToken))
96: {
97: using (var secureWeb = secureSite.OpenWeb())
98: {
99: if (null == secureWeb)
100: throw new SPException("Failed to open secure web");
101: action(secureSite, secureWeb, user);
102: }
103: }
104: }
105: }
106: }
107:
108: /// <summary>
109: /// Get an SPSite and SPWeb (root) reference for a given
110: /// <paramref name="url">site Url</paramref> and
111: /// <paramref name="title">web title</paramref> and execute
112: /// a given <paramref name="action">Action</paramref>.
113: /// </summary>
114: /// <param name="url">Site Url.</param>
115: /// <param name="title">Web Title.</param>
116: /// <param name="action">Action delegate.</param>
117: public static void GetWebByTitle(string url, string title, Action<SPSite, SPWeb> action)
118: {
119: if (String.IsNullOrEmpty(url))
120: throw new ArgumentNullException("url");
121: if (String.IsNullOrEmpty(title))
122: throw new ArgumentNullException("title");
123: if (null == action)
124: throw new ArgumentNullException("action");
125: using (var site = new SPSite(url))
126: {
127: using (var web = site.AllWebs[title])
128: {
129: if (null == web)
130: throw new SPException("Web not found");
131: action(site, web);
132: }
133: }
134: }
135:
136: /// <summary>
137: /// Get an SPSite and SPWeb (parent) reference for a given
138: /// <paramref name="url">site Url</paramref> and
139: /// a given <paramref name="action">Action</paramref>.
140: /// </summary>
141: /// <param name="url">Site Url.</param>
142: /// <param name="action">Action delegate.</param>
143: public static void GetParentWeb(string url, Action<SPSite, SPWeb> action)
144: {
145: if (String.IsNullOrEmpty(url))
146: throw new ArgumentNullException("url");
147: if (null == action)
148: throw new ArgumentNullException("action");
149: using (var site = new SPSite(url))
150: {
151: using (var web = site.OpenWeb())
152: {
153: if (null == web)
154: throw new SPException("Cannot open web");
155: if (web.IsRootWeb)
156: throw new SPException("Url has no parent web.");
157: using (var parentWeb = web.ParentWeb)
158: action(site, parentWeb);
159: }
160: }
161: }
162:
163: /// <summary>
164: /// Get a SPSite reference for a given <paramref name="url">site URL</paramref> and execute
165: /// a given <paramref name="action">Action</paramref>. Elevate to SharePoint service account
166: /// before opening.
167: /// </summary>
168: /// <param name="url">Site Url.</param>
169: /// <param name="action">Action delegate.</param>
170: public static void GetSiteElevated(string url, Action<SPSite> action)
171: {
172: SPSecurity.RunWithElevatedPrivileges(() => GetSite(url, action));
173: }
174:
175: /// <summary>
176: /// Get an SPSite and SPWeb reference for a given <paramref name="url">site URL</paramref> and execute
177: /// a given <paramref name="action">Action</paramref>. Elevate to SharePoint service account
178: /// before opening.
179: /// </summary>
180: /// <param name="url">Web Url.</param>
181: /// <param name="action">Action delegate.</param>
182: public static void GetWebElevated(string url, Action<SPSite, SPWeb> action)
183: {
184: SPSecurity.RunWithElevatedPrivileges(() => GetWeb(url, action));
185: }
186:
187: /// <summary>
188: /// Get an SPSite and SPWeb (root) reference for a given <paramref name="url">site URL</paramref> and execute
189: /// a given <paramref name="action">Action</paramref>. Elevate to SharePoint service account
190: /// before opening.
191: /// </summary>
192: /// <param name="url">Site Url.</param>
193: /// <param name="action">Action delegate.</param>
194: public static void GetRootWebElevated(string url, Action<SPSite, SPWeb> action)
195: {
196: SPSecurity.RunWithElevatedPrivileges(() => GetRootWeb(url, action));
197: }
198:
199: /// <summary>
200: /// Get an SPSite and SPWeb (root) reference for a given
201: /// <paramref name="url">site Url</paramref> and
202: /// <paramref name="title">web title</paramref> and execute
203: /// a given <paramref name="action">Action</paramref>.
204: /// Elevate to SharePoint service account before opening.
205: /// </summary>
206: /// <param name="url">Site Url.</param>
207: /// <param name="title">Web Title.</param>
208: /// <param name="action">Action delegate.</param>
209: public static void GetWebByTitleElevated(string url, string title, Action<SPSite, SPWeb> action)
210: {
211: SPSecurity.RunWithElevatedPrivileges(() => GetWebByTitle(url, title, action));
212: }
213:
214: /// <summary>
215: /// Get an SPSite and SPWeb (parent) reference for a given
216: /// <paramref name="url">site Url</paramref> and
217: /// a given <paramref name="action">Action</paramref>.
218: /// Elevate to SharePoint service account before opening.
219: /// </summary>
220: /// <param name="url">Site Url.</param>
221: /// <param name="action">Action delegate.</param>
222: public static void GetParentWebElevated(string url, Action<SPSite, SPWeb> action)
223: {
224: SPSecurity.RunWithElevatedPrivileges(() => GetParentWeb(url, action));
225: }
226:
227: /// <summary>
228: /// Get an SPSite and SPWeb reference for a given <paramref name="url">site URL</paramref> and
229: /// <paramref name="username"/> and execute
230: /// a given <paramref name="action">Action</paramref>.
231: /// Elevate to SharePoint service account before opening.
232: /// </summary>
233: /// <remarks>Username must be a user in the site.</remarks>
234: /// <param name="url">Site Url.</param>
235: /// <param name="username">Username with access to the web.</param>
236: /// <param name="action">Action delegate.</param>
237: public static void GetSecureWebElevated(string url, string username, Action<SPSite, SPWeb, SPUser> action)
238: {
239: SPSecurity.RunWithElevatedPrivileges(() => GetSecureWeb(url, username, action));
240: }
241:
242: #endregion Methods
243: }
Using the above helper class, developers need never allocate web or site objects. Furthermore, since each method call above cleans up memory after execution, developers never need to worry about too many web or site instances lying around waiting for garbage collection (also greeted with a nice error message in the log).