Take the 2-minute tour ×
SharePoint Stack Exchange is a question and answer site for SharePoint enthusiasts. It's 100% free, no registration required.

I'm building a Site Definition that will be the core of a SharePoint product.

I want to use best practices building the data access architecture.

Since I do not know what the URL of the site will be, it seems SPContext.Current.Web is a great way to access lists on this site.

However, I often see people manually entering the SPWeb location, or using functions like ServerRelativeUrl + "/lists/listname" to access a site list.

Based on my needs (highly variable URL), what is the best access method for pulling list data?

share|improve this question
add comment

2 Answers

up vote 7 down vote accepted

Any kind of hardcoded path is, in general, opposite from best practice so opening a SPWeb or SPList object directly from its full server URL is a no-no.

To get the SPWeb object, if you are sure your code will always run in your desired web it is perfectly okay to use SPContext.Current.Web. In all other cases, you might want to look at something like the Service Locator pattern, or some other way of finding your way (property bag, list item in a central config list, etc.). Storing web URLs in the web.config is IMHO not best practice.

You should always avoid using SPWeb.Lists[string listName], as it enumerates all lists (which is slow, and will throw AccessDenied if the user does not have proper privileges for that). Use SPWeb.Lists[Guid uniqueId] instead, or SPWeb.GetList().

For SPList objects from a definition that you control (such as a pre-defined list in an applicative site), the site-relative URL of the list is known and fixed so it's okay to open it with GetList(SPWeb.ServerRelativeUrl + "/lists/myListUrl").

One important caveat, SPWeb.ServerRelativeUrl is not always terminated by a slash. If you are at the root, it will be "/", and in all other cases it will be "someUrl/subsite" without an ending slash. So to properly concatenate with the list's Web-relative Url you need to handle that case for example by using SPUtility.ConcatUrls.

If your product exposes webparts or application pages (in _layouts), they are potentially accessible from other site collections (where they would not make much sense) and you should protect against that, for example by setting a SPWeb property bag entry upon provisioning the site and verifying against that in the applicative pages.

Now, all that being said, for real best-practice advanced kung fu (but unfortunately rarely seen), you should encapsulate all your SP* accesses in repository patterns. Instead of sprinkling SPWeb.GetList() everywhere in your code, use e.g. ImageRepository.Current() which will return your product's image store. That repository should return custom (POCO) 'Image' objects tailored to your needs, abstracted away from SPListItem objects.

Be aware that handling SPList or SPListItem objects outside of the scope of their SPWeb or SPSite is a sure way of running into SPDispose leaks and performance hits, as a number of methods in those objects re-open their parent web without disposing it (but internal caching mitigates that a bit).

Sorry for all these odd bits thrown together. I'll gladly elaborate on any of those points.

share|improve this answer
    
Wow! Above and beyond my friend! I'd love more details on certain points you raised, and would be happy to open a new ticket for recognition. Currently, I have a data access layer which has methods like List<Community> GetAllCommunitiesByXXX() and returns a Generic List of Objects to prevent dispose leaks. Am I on the right track? Maybe I could send you an email or something. –  Wesley Jun 30 '12 at 4:25
    
I think you are /best/ track. You will see this makes it much more testable, portable and reusable. What other points did you want to discuss? –  Louis Jul 5 '12 at 0:25
add comment

It depends on the "context". In a web part or application page, use SPContext. A lot of example code you see on the web uses a console app for simplicity - these would use the SPSite constructor with a string parameter representing the url. In a Feature receiver you'd use (SPWeb)properties.Feature.Parent.

Bottom line is, if the code is being executed inside SharePoint, you'll be able to get that variable url without too much effort. If the code executes outside SharePoint(like a console app, winforms or client object model), you'll have to supply the context.

share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.