Is possible to inherit from SharePoint classes such like: SPWeb, SPList etc.
or this classes are sealed? I couldn't find right answer.
Chris
Thanks for replys.
Rich, you are right - the constructors are internal. So it means that I coudn't extend the functionality of these classes in any elegance way?
According to Reflector, SPWeb is not sealed in either 2007 or 2010.
2007:
[SharePointPermission(SecurityAction.LinkDemand, ObjectModel=true),
SharePointPermission(SecurityAction.LinkDemand, ObjectModel=true),
SharePointPermission(SecurityAction.LinkDemand, ObjectModel=true),
SharePointPermission(SecurityAction.InheritanceDemand, ObjectModel=true)]
public class SPWeb : IDisposable, ISecurableObject
2010:
[SubsetCallableType,
ClientCallableType(Name="Web", ServerTypeId="{A489ADD2-5D3A-4de8-9445-49259462DCEB}", FactoryType=typeof(SPObjectFactory), ObjectIdentityPropertyName="CanonicalId"),
SharePointPermission(SecurityAction.InheritanceDemand, ObjectModel=true),
SharePointPermission(SecurityAction.LinkDemand, ObjectModel=true),
SharePointPermission(SecurityAction.LinkDemand, ObjectModel=true),
SharePointPermission(SecurityAction.LinkDemand, ObjectModel=true)]
public class SPWeb : SPSecurableObject, IDisposable
However, in both versions, the class only has internal constructors, so while Visual Studio will let you try to inherit from the class, it will not compile:
The type 'Microsoft.SharePoint.SPWeb'
has no constructors defined
According to their MSDN pages, the classes are not sealed:
SPWeb Class
SPList Class
Even though you may be able to inherit from those classes, I don't see the point since you can't force SharePoint to use them internally.
It may make more sense to provide your added functionality via Extension Methods rather than actually inheriting from the base classes.
SPWeb and SPList are sealed in SharePoint 2007, see: http://blogs.msdn.com/b/francischeung/archive/2008/08/22/unit-testing-sharepoint-2007-applications.aspx
But they are not sealed in SharePoint 2010, see: http://my.safaribooksonline.com/9781435456457/365
Of course they can be extended, simply using Extension Methods - http://msdn.microsoft.com/en-us/library/bb383977.aspx
As an example I'm trying to push a bit, you can take a look at ItemTools, or ListTools or other source files in https://github.com/kerray/NAVERTICA-SPTools
I think a lot of SharePoint server object model programmer had came to this issue.
At first, I simply start with a helper class as a wrapper for SPWeb, which use Managed Navigation.
As the requirement became more complicate, I have to deal with more than one type of SPWeb. So, I refacted the code, create a Factory class to instantiate typed SPSite and SPWeb. Which bind a SPWeb with Managed metadata term, and store the type information in both SPWeb property and Term custom property.
I would like to help Microsoft to find out if this is a design that make sense. And if it worthwhile for Microsoft to start a opensource project for this. Since sometimes programmers have to focus on business logic, don't want to implement Factory, Abstract Factory again and again.
https://social.msdn.microsoft.com/Forums/office/en-US/62c1355f-0b71-49b7-967a-648830bd6dfa/creating-a-factory-class-with-sharepoint-server-side-api-to-instantiate-a-wrapper-class-around#62c1355f-0b71-49b7-967a-648830bd6dfa
Related
When handling the Selected event of a EntityDataSource, the Results property of the EntityDataSourceSelectedEventArgs returns an ObjectView collection of my entities. I'm not sure what this class is. This link to the Namepace doesn't mention the class.
Is there any documentation on this System.Data.Objects.ObjectView collection class? How would I convert an ObjectView<T> to a List<T>? Perhaps it's as simple as enumerating the collection and adding the items to a new List<T>, but some information about the class would be useful.
The ObjectView class is internal and therefore you cannot find it on MSDN. The important bit of information is that it implements IBindingListInterface
The Microsoft CRM advanced developer extensions have gotten me a little spoiled with their early binding for calls made to CRM's webservices.
I'm writing a plugin right now and I'd like to access attributes defined in the pre-image. All the examples cast the preimage as Microsoft.Xrm.Sdk.Entity which uses late binding to access it's attributes. I dislike hardcoding all those string's for attribute names into my plugin and would like to find a method that avoids it by using early binding.
Here is an example of a cast
var preMessageImage = (Microsoft.Xrm.Sdk.Entity)context.PreEntityImages["MyPreImage"];
But I have to use late binding to access the properties
var myProperty = preMessageImate.Properties["MyProperty"];
Is there any way to cast this preimage to an xrm object that has all the properties defined using early binding so I don't have to hardcode all the property names?
You should first use the crmsvcutil tool in the SDK to generate "early-bound" Xrm entities and include that code file in your plugin codebase.
I suggest omitting the 'DataContextName' command-line arg so not context is generated.
For more information check here on MSDN: CrmSvcUtil on MSDN
Next, you should use the ToEntity<T> method on the Entity class to get a strongly-typed specific entity. More info here: ToEntity on MSDN
If you start SharePoint and learn about disposing SPSite and SPWeb, almost everybody suggests to use the "using"-construct if you work with new instances of SPSite and SPWeb.
using (SPSite s = new SPSite("http://yourserver")
{
using (SPWeb web = s.OpenWeb("http://yourweb")
{
// do fancy stuff here
}
}
I did that too. However, if you look into the SPSite.Dispose() method, you'll notice that SPSite keeps a reference of its SPWebs created by SPSite.OpenWeb(). On SPSite.Dispose(), all SPWebs tied to this SPSite are diposed. I think (but Im not sure) that virtually all methods which are creating a new SPWeb are adding this SPWeb to the internal collection 'm_openedWebs'.
This being said, I wonder why you would ever dispose a SPWeb object? Are there any real-world scenarios were you should dispose SPWeb objects?
UPDATE
I just realized, that I spared a little detail which might be important. The SPSite object does not call Dispose() on its child SPWebs, but it is calling Close(). In the current implementation of SharePoint, this is the same as Dispose(), becasue SPWeb.Dispose() just contains:
public void Dispose()
{
this.Close();
}
So one reason for disposing SPWeb objects might be to be compatible to future SharePoint implementations where SPWeb.Dispose() does not only call SPWeb.Close(). I still find it akward to "double-dispose" my SPWebs only for that reason.
You're right, disposing the SPSite will close the associated SPWeb objects.
The main scenario where you want to close SPWeb's right away is when you do something like:
foreach (SPWeb web in site.AllWebs)
{
// do something with the web object
web.dispose(); // <-- this is mandatory!
}
For normal opening and closing of one SPSite/SPWeb this doesn't matter but I would argue it is still good practice (especially for new SharePoint developers).
If you haven't already, I would highly recommend reading Stefan Goßner's post: http://blogs.technet.com/b/stefan_gossner/archive/2008/12/05/disposing-spweb-and-spsite-objects.aspx
That's an interesting dilemma, binford and I certainly wasn't aware until now that the SPSite object was implicity disposing of any SPWebs tied to it.
If what you're saying is so, then the only reason I could think you might still want to explicitly handle the SPWeb might be when the scenario is more complex, for example using two or more SPWebs where the time to construct and destruct them thus becomes a more important consideration.
For example, imagine you had 7 SPWeb instantiations inside your SPSite using block, each performing a series of long-running and complex operations before disposing -- you'd want to be closing and disposing of these objects as soon as possible to maximise memory resources and garbage collect efficiently.
That said, in the most basic of cases (1 SPSite, 1 SPWeb as you have detailed above), I am beginning to wonder if the SPWeb explicit dispose is at all necessary.
More research and opinions needed I think, but thank you for alerting my attention to this.
If you're reading/writing data to/from multiple SPWebs instantiated within an SPSite, and you lose control over which you have open, you will soon encounter data concurrency issues, where you're having to do AllowUnSafeUpdates all over the place which is generally bad practice.
Chris O'Brien has a good blog post on SPWeb and IDisposable:
http://www.sharepointnutsandbolts.com/2008/06/disposing-sharepoint-objects-what-they.html
I would make sure you are using SPDisposeCheck. After Visual Studio, this is the must
have tool for SharePoint development. The latest version now includes rules on when not to dispose objects:
We have added several checks on when “NOT” to Dispose objects instantiated by SharePoint internally. These newly reported “DO NO DISPOSE” (DND) rules were unreported by SPDisposeCheck v1.3.* .
I read the msdn article about disposing objects in http://msdn.microsoft.com/en-us/library/ee557362(office.14).aspx
now I'm really confused about this.
consider this example
SPList List = SPContext.Current.Web.Lists["DemoList"];
SPListItem Item = List.GetItemById(ItemID);
is it ok to use this or better to use:
using (SPWeb web = SPContext.Current.Web)
{
SPList List= web.Lists["DemoList"];
SPListItem Item = List.GetItemById(ItemID);
}
or it makes no difference
thanks
You don't need to dispose of the SPWeb in this case as you didn't create it. You only need to dispose of an SPWeb object (and SPSite object) if you are responsible for instantiating the object.
So in the following instance you would need to call dispose (or have dispose automatically aclled using the "using" statement) as you were responsible for new-ing up the SPSite..
void CombiningCallsBestPractice()
{
using (SPSite siteCollection = new SPSite(SPContext.Current.Web.Url))
{
using (SPWeb web = siteCollection.OpenWeb())
{
// Perform operations on site.
} // SPWeb object web.Dispose() automatically called.
} // SPSite object siteCollection.Dispose() automatically called.
}
The "using" statement is equivalant to calling web.Dispose() at the end of the block, but is more readable and the disposal is less likely to be forgotten.
If you are worried about whether you have any undisposed objects in your SharePoint code I strongly recommend using SPDisposeCheck. This tool will analyse your assembly and point out all the places where you could have an undisposed object. It's great! :-)
I read a statement about SPWeb once, which said "SPWeb is like a cute girl - if it is not yours, don't touch it, if it's yours - take care of it".
So, if you created a new instance of SPWeb class, you have to dispose it. If you took it from somewhere else - the SPContext.Current object - leave it as is.
UPDATE
Oh, I found the post and it is a little different:
Dispose is like a pretty girl, if you
see it, call it... but don't break
rule #1. i.e. don't call a pretty girl
that isn't confirmed unattached, .. if
her large mammalian boyfriend finds
out, he may knock your teeth out. This
rule applies to general .NET as well.
Just to be clear, since the link you reference is to SharePoint 2010... There are several changes between WSS 3.0 and SharePoint 2010 Foundations (essentially WSS 4.0), one of which is that you are no longer required to dispose of a SPWeb object, only the SPSite object when referenced from the SPSite in a using block. Seems to be a bit out of synch with the link you provided. I am not sure if that documentation is out of date or will be updated. However, I have heard the SPWeb not needing a dispose call several times. Not sure in what context that is true now after reading that article. Something that will be further expanded I assume as the release date approaches.
In regards to the code you reference above, it as others have said, since you have not created the object, you do not have to manage the object. In fact, if you get a SPSite (and SPWeb in WSS 3.0) from the SPContext object you will run into issues with SharePoint if you dispose of the object, since the SharePoint runtime instantiated it.
As mentioned above, SPDisposeChecker is a very useful tool. Roger Lamb also has a great article explaining Dispose best practices
http://msdn.microsoft.com/en-us/library/aa973248.aspx
http://blogs.msdn.com/rogerla/archive/2008/02/12/sharepoint-2007-and-wss-3-0-dispose-patterns-by-example.aspx
Such as:
Sealed Methods you might have liked to extend
Exceptions thrown are more vague than is helpful
Elimination of Connected Content which was a major feature in MCMS 2002
HTML is stripped from fields when stored and returned. No easy option to work around this problem
Creating an SPWeb takes an eternity.
Nonexistant migration path from MCMC 2002
I wish that the Sharepoint object model was purely managed code. Although having .NET wrappers is convenient, having to worry about disposing the many objects that implement IDisposable is a pain. It's so easy to run into memory issues when dispose does not get called in a WSS app. And I thought the reason for moving to .NET was to free developers from having to deal with memory management...
How about refactoring Properties that result in additional database calls to methods instead, for example the Items property on SPList.
Any of the SPList API could use a complete rewrite. Trying to deal with libraries with nested folders is a complete nightmare with the list being completely flattened with no obvious hierarchical structure.
Another wonderful addition would be adding interfaces to SPWeb, SPList and other Sharepoint classes to aid testing.
Has anyone seen this method:
http://msdn.microsoft.com/en-us/library/microsoft.sharepoint.spsecurity.runwithelevatedprivileges.aspx This method shows the unbelievable nonsense that Sharepoint exposes to developers.
My personal favourite is the SPField.GetFieldValue Method. I have no idea why they designed it the way they did, but to me it does hardly make sense. To get a object out of a ListItem you have to do somethine like:
SPField field = ((SPList)list).Fields.GetField("FieldName");
object fieldValue = field.GetFieldValue(((SPListItem)item)[field.Title].ToString());
Getting an object out of a ListItem is IMO a basic operation, so this should not be that complicated.
Inconsistencies when passing field names to methods or arrays. For example:
SPFieldCollection.ContainsField(): Internal name or display name
SPFieldCollection.GetField(): Internal name or display name
SPFieldCollection.GetFieldByInternalName(): Internal name
SPFieldCollection.Item: Display name
SPListItem.Item: Internal name or display name
SPListItem.GetFormattedValue(): Internal name or display name
SPViewFieldCollection.Exists: Internal name
To put the icing on the cake, there is usually no documentation about whether a method takes internal and/or display name.