I'm currently doing some test where I try to delete a site collection programmatically. Thereby I realized some strange behavior by SharePoint.
I used the following code to test the site collection deletion.
private static void DeleteSiteCollection(string urlSiteToDelete)
{
SPSecurity.RunWithElevatedPrivileges(delegate()
{
SPWebApplication webApp = SPWebApplication.Lookup(new Uri("http://wssdev06"));
webApp.Sites.Delete(urlSiteToDelete);
webApp.Update();
});
}
So when I call the method with the url of an existing site collection the site collection will be deleted as expected. But when I call the method with null, the empty string or an url which is not connected to a site collection then SharePoint deletes the site collection which resides under root (e.g. http://wssdev06/).
I'm not sure if I'm too dump to use this SPSiteCollection.Delete() method or if I did not understand the conecpt of site collections and managed paths, but I think this a really strange and alarming behavior.
I could repoduce this behavoir on different web application but had no option to test in on another SharePoint environment yet.
So am I doing something wrong or is this a bug?
UPDATE:
So I did some more investigations and realized that this must have something to do with the indexer of the SPSiteCollection class which returns the root site collection if there is no site collection located under the given url. Looks like a bug.
Whenever you ask SharePoint to find a Site Collection using an Url it'll do it's best to return a SPSite even if it means that it'll have to ignore part of the Url.
Sometimes this is a very good thing. f.i. if you have the full url of a list and want to find the corresponding SPSite and SPWeb.
But it can be very dangerous like when you're deleting Site collections and maybe make a spelling mistake.
If you want to make sure you get the right Site Collection the lookup the SPSite first and check that the SPSite you get has the Url that you want.
BR
Per
Your code looks right. One thought would be to add a check of the sites collection to make sure the site you want to delete is in the sites collection. I realize this does not answer your question.
This sounds like exactly the issue described in Microsoft's KB 968474 - stsadm can inadvertently delete a root site collection if erroneous URL path used. Similar to your symptoms, when using stsadm - o restore, "If the URL path is incorrect then the deletion and restore is attempted against the only valid path which is the root site collection of the URL."
It sounds to me like there is some bug in the underlying site delete API, as you suspected. Possibly, the algorithm looks for a "closest match" rather than "exact match".
Enumerating the Site Collections and validating an exact match might be the best way to avoid this. However, I wouldn't say you're doing anything wrong as this is very close to the Microsoft sample code and the documentation for the function gives no warning about passing invalid URLs.
Related
I have configured my Liferay 7 site with a terms of use web content document. It works perfectly when new users log in for the first time.
However, I need to be able to provide a link to review the terms of use. The only thing I see is in the Liferay Portal struts-config.xml file, which is "/portal/terms_of_use". But this link appended to my hostname is not working. I get a "Not Found" error page ("The requested resource could not be found.").
Am I using the wrong URL? I've tried searching for what the URL would be and have not found anything, which is surprising since I would think this is a common requirement.
With the routing of web-stuff to OSGi bundles, there's no longer any top-level URL that can be specified this way (there may never have been one). However, there is a way to get to it:
http://localhost:8080/c/portal/terms_of_use requires login, but results in the (in my case unconfigured) terms of use. The /c within the URL targets struts (and maybe something else - the /portal within targets a certain bundle (portal-web in this case)
We work on a product that is a series of components that could be installed on different CMSs and provide different services. We take a CMS agnostic approach and try to use the same code in all the CMSs as much as possible (we try to avoid using CMS API as much as we can).
Some part of the code needs to work with the current URL for some redirections so we use Request.Url.ToString() that is something that has worked fine in other environments but in Kentico instead of returning the current page we always get a reference to CMSPages/PortalTemplate.aspx with a querystring parameter aliasPath that holds the real URL. In addition to that, requesting the Template page using a browser gives you a 404 error.
Example:
Real URL (this works fine on a browser):
(1) https://www.customer.com/Membership/Questionnaire?Id=7207f9f9-7354-df11-88d9-005056837252
Request.Url.ToString() (this gives you a 404 error on a browser):
(2) https://www.customer.com/CMSPages/PortalTemplate.aspx?Id=7207f9f9-7354-df11-88d9-005056837252&aliaspath=/Membership/Questionnaire
I've noticed that the 404 error is thrown explicitly by the template code when invoked directly. Please see below code from Page_Init method of PortalTemplate.aspx.cs:
var resolvedTemplatePage = URLHelper.ResolveUrl(URLHelper.PortalTemplatePage);
if (RequestContext.RawURL.StartsWithCSafe(resolvedTemplatePage, true))
{
// Deny direct access to this page
RequestHelper.Respond404();
}
base.OnInit(e);
So, if I comment the above code out my redirection works fine ((2) resolves to (1)). I know it is not an elegant solution but since I cannot / don't want to use Kentico API is the only workaround I could find.
Note that I know that using Kentico API will solve the issue since I'm sure I will find an API method that will return the actual page. I'm trying to avoid that as much as possible.
Questions: Am I breaking something? Is there a better way of achieving what I trying to accomplish? Can you think on any good reason I shouldn't do what I'm doing (security, usability, etc)?
This is kind of a very broad question so I was not able to find any useful information on Kentico docs.
I'm testing all this on Kentico v8.2.50 which is the version one of my customers currently have.
Thanks in advance.
It's not really recommended to edit the source files of Kentico, as you may start to run into issues with future upgrades and also start to see some unexpected behaviour.
If you want to get the original URL sent to the server before Kentico's routing has done its work, you can use Page.Request.RawUrl. Using your above example, RawUrl would return a value of /Membership/Questionnaire?Id=7207f9f9-7354-df11-88d9-005056837252, whereas Url will return a Uri with a value of https://www.customer.com/CMSPages/PortalTemplate.aspx?Id=7207f9f9-7354-df11-88d9-005056837252&aliaspath=/Membership/Questionnaire (as you stated).
This should avoid needing to use the Kentico API and also avoid having to change a file that pretty much every request goes through when using the portal engine.
If you need to get the full URL to redirect to, you can use something like this:
var redirectUrl = Request.Url.GetLeftPart(UriPartial.Authority) + Request.RawUrl;
I'm using the Search API as defined here:
https://developers.box.com/docs/#search
It works well, though I noticed that when I make a folder on the site, then immediately call the API searching for that folder name, it doesn't appear in the results for a minute or so. Is there something I'm doing wrong, or some way to force it to do a live search? Thanks.
You're not doing anything wrong. It just takes a little bit of time for the search indexes to be updated with the new file/folder metadata. There's nothing you can do client-side to speed this up.
If you need immediate access that new folder, consider saving the folder ID that's returned in the response of the Create a New Folder request.
I am trying to get a list of folders in an array from a remote webdav. I am using the PROPFIND method querying for property 'isfolder', which although it is not standard it is contemplated in 'Additional WebDAV Collection Properties'. Then, I will parse the XML response to build up the array. However, in the response, I get a 'Resource not found' for this property. I am using the query against an IIS server.
My question, which seems to be answered already with my results (need confirmation though), is:
-Doesn't IIS have 'isfolder' property by default?
Then, how can I include it?
And, is there a better way to get a list of folders from a webdav directory?
Many thanks in advance.
You don't need any custom properties. Just check the DAV:resourcetype property.
Besides buying a third party, what is the best approach to extending the CQWP control to include content from a seperate site collection?
You can not override the content query webpart to query another site collection. It uses the SPSiteDataQuery http://msdn.microsoft.com/en-us/library/microsoft.sharepoint.spsitedataquery.aspx , this is limited to the current site collection. But you could create a custom webpart that has similar function but looks to a site collection by url rather than from the SPContext. Example:
using (SPSite site = new SPSite("http://server/"))
{
// build a SPSiteDataQuery
// include the CAML query
// use the datatable of results to create XML
// use XSLT to transform XML into HTML
}
Actually, we figured it out. We were successfully able to inherit from CQWP and use a ton of reflector to reproduce a lot of the CQWP code and got it working quite well to query other site collections, as well as the current. The code involved was not for the faint of heart though.