I a console application that creates a sub sites under a site collection
The site collection accepts only forms based user.
Now, when i run the console application, its with windows credentials.
I need some way to run the code in console app that creates sub site to run under forms user who is admin to that site collection.
Please let me know your suggestions.
Thanks
You need to create a new Web service within the Central Administration Web application ([12 hive]\AMDISAPI) and add a function that creates subsites.
Here's an example - the hstCreateSubSite function from the SharePoint for Hosters project:
/// <summary>
/// Method to create a Sub site for a site collection
/// </summary>
/// <param name="strSiteURL">url of the sitecollection i.e. "http://www.sitea.com"</param>
/// <param name="subsitePath">the path to the subsite i.e. inventory</param>
/// <param name="strTitle">sub site title</param>
/// <param name="strDesc">sub site description</param>
/// <param name="strTemplate">a valid templateID</param>
/// <param name="nLCID">the LCID for the language i.e. 1033 for english</param>
[WebMethod]
public void hstCreateSubSite(string strSiteURL, string subSitePath, string strTitle, string strDesc, string strTemplate, uint nLCID)
{
SPSite oSite = new SPSite(strSiteURL);
SPWeb oSubSiteWeb = oSite.OpenWeb();
SPWeb oWeb = null;
if (String.IsNullOrEmpty(strDesc)) strDesc = null;
if (String.IsNullOrEmpty(strTitle)) strTitle = null;
try
{
// elevate permissions to allow user to create a new site.
SPSecurity.RunWithElevatedPrivileges(delegate()
{
// the subsite will inherit permissions and will not convert the site if it exists
oWeb = oSubSiteWeb.Webs.Add(subSitePath, strTitle, strDesc, nLCID, strTemplate, false, false);
SPNavigationNodeCollection nodes = oSubSiteWeb.Navigation.TopNavigationBar;
SPNavigationNode navNode = new SPNavigationNode(strTitle, subSitePath);
nodes.AddAsLast(navNode);
oWeb.Navigation.UseShared = true;
// create entry in property bag to store template and url in the subsite.
oWeb.AllowUnsafeUpdates = true;
// add the Templateid to the property bag. This needs to be done becuase
// sites that are created from site templates (.stp) do not retain the templateid.
oWeb.Properties.Add("STP_ID", strTemplate);
oWeb.Properties.Update();
oWeb.AllowUnsafeUpdates = false;
});
}
catch (Exception ex)
{
throw ex;
}
finally
{
//dispose objects
if (oWeb != null)
oWeb.Dispose();
if (oSite != null)
oSite.Dispose();
}
}
Related
I am working on a requirement where I need to create a site collection in SharePoint using client side api. I know server side we can do it using self service site creation api. Also I know in case of SharePoint Online , we have Microsoft.Online.SharePoint.Client.Tenant.dll that we can use to create site collection However in my case I have a On premise environment (SharePoint 2013) where I need to create a site collection thru client side api. Can you please let me know if there is any API that I can use for this requirement.
Thanks for any Help you can provide on this.
This is not possible to do by using the CSOM, on an on-premise environment.
As you mentioned, it is possible on the SPO environment using the library that you listed (Microsoft.Online.SharePoint.Client.Tenant.dll).
I'm not sure if this will help, but here is code that could create a site inside of the current site collection:
You will also need to add using statements for System.Collections.Generic and System.Text.
// Starting with ClientContext, the constructor requires a URL to the
// server running SharePoint.
ClientContext context = new ClientContext("http://SiteUrl");
WebCreationInformation creation = new WebCreationInformation();
creation.Url = "web1";
creation.Title = "Hello web1";
Web newWeb = context.Web.Webs.Add(creation);
// Retrieve the new web information.
context.Load(newWeb, w => w.Title);
context.ExecuteQuery();
label1.Text = newWeb.Title;
This code was taken directly from here: http://msdn.microsoft.com/en-us/library/fp179912.aspx
How to create site collection via SharePoint 2013 Managed CSOM
Tenant.CreateSite method from Microsoft.Online.SharePoint.Client.Tenant.dll assembly is intended for site collection creation:
/// <summary>
/// Create a new site.
/// </summary>
/// <param name="context"></param>
/// <param name="url">rootsite + "/" + managedPath + "/" + sitename: e.g. "https://auto.contoso.com/sites/site1"</param>
/// <param name="title">site title: e.g. "Test Site"</param>
/// <param name="owner">site owner: e.g. admin#contoso.com</param>
/// <param name="template">The site template used to create this new site</param>
/// <param name="localeId"></param>
/// <param name="compatibilityLevel"></param>
/// <param name="storageQuota"></param>
/// <param name="resourceQuota"></param>
/// <param name="timeZoneId"></param>
internal static void CreateSite(ClientContext context, String url, String owner, String title =null, String template = null, uint? localeId = null, int? compatibilityLevel = null, long? storageQuota = null, double? resourceQuota = null, int? timeZoneId = null)
{
var tenant = new Tenant(context);
if (url == null)
throw new ArgumentException("Site Url must be specified");
if (string.IsNullOrEmpty(owner))
throw new ArgumentException("Site Owner must be specified");
var siteCreationProperties = new SiteCreationProperties {Url = url, Owner = owner};
if (!string.IsNullOrEmpty(template))
siteCreationProperties.Template = template;
if (!string.IsNullOrEmpty(title))
siteCreationProperties.Title = title;
if (localeId.HasValue)
siteCreationProperties.Lcid = localeId.Value;
if (compatibilityLevel.HasValue)
siteCreationProperties.CompatibilityLevel = compatibilityLevel.Value;
if (storageQuota.HasValue)
siteCreationProperties.StorageMaximumLevel = storageQuota.Value;
if (resourceQuota.HasValue)
siteCreationProperties.UserCodeMaximumLevel = resourceQuota.Value;
if (timeZoneId.HasValue)
siteCreationProperties.TimeZoneId = timeZoneId.Value;
var siteOp = tenant.CreateSite(siteCreationProperties);
context.Load(siteOp);
context.ExecuteQuery();
}
//Usage
const string username = "***#***.onmicrosoft.com";
const string password = "***";
const string tenantAdminUrl = "https://***-admin.sharepoint.com/";
const string newSiteCollUrl = "https://contoso.sharepoint.com/sites/finance"
var securedPassword = new SecureString();
foreach (var c in password.ToCharArray()) securedPassword.AppendChar(c);
var credentials = new SharePointOnlineCredentials(username, securedPassword);
using (var context = new ClientContext(tenantAdminUrl))
{
context.Credentials = credentials;
CreateSite(context, newSiteCollUrl,username);
}
It is available in the April 2014 CU
http://blogs.msdn.com/b/vesku/archive/2014/06/09/provisioning-site-collections-using-sp-app-model-in-on-premises-with-just-csom.aspx
I have this event receiver c# class that I am trying to implement on a Sharepoint site. It did not work. I have deployed it from visual studio 2010 after it was build ok. Does anyone see what is the problem? Is the code ok? or is the problem on the SP? Thank you.
- here is the new code
using System;
using System.Security.Permissions;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Security;
using Microsoft.SharePoint.Utilities;
using Microsoft.SharePoint.Workflow;
namespace EventReceiverCFolder.EventReceiver1
{
/// <summary>
/// List Item Events
/// </summary>
public class EventReceiver1 : SPItemEventReceiver
{
/// <summary>
/// An item is being added.
/// </summary>
public override void ItemAdded(SPItemEventProperties properties)
{
try
{
if (properties.ListTitle == "CF") // list where the item was added
{ // if item was added to this list then create a folder on - Dlib - list
UpdateFolder(properties);
}
}
catch (Exception ex)
{
properties.Status = SPEventReceiverStatus.CancelWithError;
properties.ErrorMessage = ex.Message;
properties.Cancel = true;
}
}
private void UpdateFolder(SPItemEventProperties properties)
{
string foldername = properties.ListItem["Title"].ToString();
try
{
SPSecurity.RunWithElevatedPrivileges(delegate()
{
//inside RunWithElevatedPriviliges I need to open a new site (an elevated site)
using (SPSite site = new SPSite(properties.Web.Site.ID))
{
using (SPWeb web = site.OpenWeb())
{
web.AllowUnsafeUpdates = true;
SPList list = web.Lists.TryGetList("DLib"); // this is doc Library where the new folder will be created
//note that we are creating a list item, not a folder - a folder IS a list item
SPListItem createdFolder = list.Items.Add(list.RootFolder.ServerRelativeUrl, SPFileSystemObjectType.Folder, null);
if (createdFolder != null)
{
createdFolder["Name"] = foldername;
createdFolder.Update();
}
list.Update();
}
}
});
}
finally { }
}
}
}
Don't do this: SPUser privilegedAccount = properties.Web.AllUsers[#"SHAREPOINT\SYSTEM"];
Read up on using SPSecurity.RunWithElevatedPrivileges. See the MSDN documentation here.
Also don't do a using (SPSite... and inside the using block you try to get the web via SPContext.Current - that web won't be elevated anymore.
The correct way is something along these lines (I didn't try this, so it' just to give you an idea where you are headed):
private void UpdateFolder(SPItemEventProperties properties)
{
string foldername = properties.ListItem["Title"].ToString();
SPSecurity.RunWithElevatedPrivileges(delegate()
{
//inside RunWithElevatedPriviliges I need to open a new site (an elevated site)
using (SPSite site = new SPSite(properties.Web.Site.ID))
{
using (SPWeb web = site.OpenWeb())
{
web.AllowUnsafeUpdates = true;
SPList list = web.Lists.TryGetList("ListTitle"); //is that really the list title?
//note that we are creating a list item, not a folder - a folder IS a list item
SSPListItem createdFolder = list.Items.Add(list.RootFolder.ServerRelativeUrl, SPFileSystemObjectType.Folder, null);
if (newFolder != null)
{
createdFolder["Name"] = foldername;
createdFolder.Update();
}
list.Update();
}
}
});
}
Also try to debug your code, set breakpoints etc.
I had to get folder name like this:
string foldername = Convert.ToString(properties.AfterProperties["Title"]);
Did you try to debug it? try to debug and tell us what error you are getting.
BUT before you debug first use sharepoint manager to see if your event receiver is attached properly.
If you dont know how to debug sharepoint event receiver then please see this
I am interested in removing a Workflow from the list using the SP Object Model. How can I do this?
I am not having much luck with Google today!
OK. So here is the function I wrote that removes the Workflow from the list. Hope it helps someone :)
/// <summary>
/// Removes the workflow.
/// </summary>
/// <param name="workflowName">Name of the workflow.</param>
/// <param name="spList">The sp list.</param>
private static void RemoveWorkflow(string workflowName, SPList spList)
{
SPWorkflowAssociation spWorkflowAssociation =
spList.WorkflowAssociations.Cast<SPWorkflowAssociation>()
.FirstOrDefault(workflowAssociation => workflowAssociation.Name.Equals(workflowName));
if (spWorkflowAssociation != null)
{
spList.WorkflowAssociations.Remove(spWorkflowAssociation.Id);
}
spList.Update();
}
Try this code,
using(SPSite oSite = new SPSite("http://localhost/"))
{
using(SPWeb oWeb = oSite.OpenWeb())
{
SPList oList = oWeb.Lists["DocumentLib"];
SPWorkflowAssociation objWorkflowAssociation = oList.WorkflowAssociations.Cast<SPWorkflowAssociation>().FirstOrDefault(workflowAssociation => workflowAssociation.Name.Equals("Approval Workflow"));
if (objWorkflowAssociation != null)
{
oList.WorkflowAssociations.Remove(objWorkflowAssociation.Id);
}
oList.Update();
}
}
Its working on my end...
I am trying to programmatically add a user like this below but get an access denied message on the Save. I'm running locally on Windows 7 and the code resides in a console app.
/// <summary>
///
/// </summary>
/// <param name="userName"></param>
/// <param name="password"></param>
/// <param name="description"></param>
public static void CreateUser(string userName, string password, string description)
{
PrincipalContext pc = new PrincipalContext(ContextType.Machine, null);
System.DirectoryServices.AccountManagement.UserPrincipal u = new UserPrincipal(pc);
u.SetPassword(password);
u.Name = userName;
u.Description = description;
u.UserCannotChangePassword = true;
u.PasswordNeverExpires = true;
u.Save();
GroupPrincipal gp = GroupPrincipal.FindByIdentity(pc, "Users");
gp.Members.Add(u);
gp.Save();
}
Any ideas? I tried supplying an administrators username and password and still get the same error.
The console app gets executed like this:
ProcessStartInfo startInfo = new ProcessStartInfo();
startInfo.UserName = userName;
startInfo.Password = securePassword;
startInfo.LoadUserProfile = true;
startInfo.UseShellExecute = false;
startInfo.FileName = batchPath;
startInfo.Arguments = operationLogID.ToString();
Process.Start(startInfo);
Here is a rough view of how the code is set up:
Console App test harness gets executed in debug mode.
I check for a user and if they don't exist..then I try and create it shown above. This is where the error occurs.
Even if you're logged in as admin, you need to run your console as admin. Here's how to launch a console as admin: http://www.howtogeek.com/howto/windows-vista/run-a-command-as-administrator-from-the-windows-vista-run-box/.
Then find your console app and run it.
Good luck!
-Michael
I am associating ribbon to my webpart. I have a need to add more than two webparts in a page.
I do not want to have a separate contextual group/tab for each webpart. Is there a way to check if a specific group/tab exists in the current ribbon on the page?
At this point, when I add more than one webpart to the page, I an getting the following error:
Item has already been added. Key in dictionary: 'Ribbon.MyContextualTabGroup' Key being added: 'Ribbon.MyContextualTabGroup'
Here is my code for your reference:
/// <summary>
/// Gets the web part contextual info.
/// </summary>
public WebPartContextualInfo WebPartContextualInfo
{
get
{
var webPartContextualInfo = new WebPartContextualInfo();
var webPartRibbonContextualGroup = new WebPartRibbonContextualGroup();
var webPartRibbonTab = new WebPartRibbonTab();
webPartRibbonContextualGroup.Id = "Ribbon.MyContextualTabGroup";
webPartRibbonContextualGroup.Command = "MyContextualTab.EnableContextualGroup";
webPartRibbonContextualGroup.VisibilityContext = "MyContextualTab.CustomVisibilityContext";
webPartRibbonTab.Id = "Ribbon.MyTab";
webPartRibbonTab.VisibilityContext = "MyContextualTab.CustomVisibilityContext";
webPartContextualInfo.ContextualGroups.Add(webPartRibbonContextualGroup);
webPartContextualInfo.Tabs.Add(webPartRibbonTab);
webPartContextualInfo.PageComponentId = SPRibbon.GetWebPartPageComponentId(this);
return webPartContextualInfo;
}
}
/// <summary>
/// Adds the contextual tab.
/// </summary>
private void AddContextualTab()
{
SPRibbon spRibbon = SPRibbon.GetCurrent(Page);
if (spRibbon == null) return;
var ribbonExtensions = new XmlDocument();
ribbonExtensions.LoadXml(_contextualTab);
spRibbon.RegisterDataExtension(ribbonExtensions.FirstChild, "Ribbon.ContextualTabs._children");
ribbonExtensions.LoadXml(_contextualTabTemplate);
spRibbon.RegisterDataExtension(ribbonExtensions.FirstChild, "Ribbon.Templates._children");
}
/// <summary>
/// The event handler for the System.Web.UI.Control.PreRender event that occurs immediately before the Web Part is rendered to the Web Part Page it is contained on.
/// </summary>
/// <param name="e">A System.EventArgs that contains the event data.</param>
protected override void OnPreRender(EventArgs e)
{
base.OnPreRender(e);
AddContextualTab();
ClientScriptManager clientScriptManager = Page.ClientScript;
clientScriptManager.RegisterClientScriptBlock(GetType(), "MyWebPart", DelayScript);
}
Contextual ribbons cannot be shared between different instances of a web part. Since the ribbon will only be displayed if your web part instance has the "focus" on the page. Therefore several instances of the web part have to create their own contextual group.
To avoid ribbon ID duplication append a web part instance specific part to the ribbon IDs. You could use the web part's ID:
webPartRibbonContextualGroup.Id = "Ribbon.MyContextualTabGroup." + ID;
// ...
webPartRibbonTab.Id = "Ribbon.MyTab." + ID;
// etc.