SharePoint 2010: feature receiver code executed from UI, not from PowerShell or stdadm - sharepoint

I have a WSP containing a web scope feature with the following code:
using System;
using System.Runtime.InteropServices;
using System.Security.Permissions;
using Microsoft.SharePoint;
using Microsoft.SharePoint.Security;
namespace Macaw.DualLayout.Samples.Features.DualLayoutSampleEmpty_Web
{
[Guid("8b558382-5566-43a4-85fa-ca86845b04b0")]
public class DualLayoutSampleEmpty_WebEventReceiver : SPFeatureReceiver
{
public override void FeatureActivated(SPFeatureReceiverProperties properties)
{
using (SPWeb web = (SPWeb)properties.Feature.Parent)
{
using (SPSite site = (SPSite)web.Site)
{
Uri uri = new Uri(site.Url + "/_catalogs/masterpage/DLSampleEmpty.master");
web.CustomMasterUrl = uri.AbsolutePath; // Master for all publishing pages
web.Update();
}
}
}
public override void FeatureDeactivating(SPFeatureReceiverProperties properties)
{
using (SPWeb web = (SPWeb)properties.Feature.Parent)
{
using (SPSite site = (SPSite)web.Site)
{
Uri uri = new Uri(site.Url + "/_catalogs/masterpage/v4.master");
web.CustomMasterUrl = uri.AbsolutePath; // Master for all publishing pages
web.Update();
}
}
}
}
}
I do F5 deployment from Visual Studio 2010.
When I activate the feature from UI I get into my breakpoint in the feature code, the feature code is executed.
When I activate the feature from PowerShell:
Enable-SPFeature -Url http://myserver/sites/publishing/empty -Identity MyFeatureName -force -verbose
or with STSADM:
stsadm -o activatefeature -name MyFeatureName -url http://myserver/sites/Publishing/Empty -force
I see that the feature is activated (in the UI), but I don't hit my breakpoint and the feature receiver code is NOT executed.
Any ideas?

If you use powershell or stsadm the feature will not run in the context of the IIS worker process. What do you attach VS studio to when you debug?
When debugging stsadm tasks I usually add:
System.Diagnostics.Debugger.Launch();
to the code and you will be prompted to attach a debugger when the command is run. Crude but easy. (Don't forget to remove)

-"By default, when you run a Visual Studio SharePoint application, its features are automatically activated for you on the SharePoint server. However, this causes problems when you debug feature event receivers, because when a feature is activated by Visual Studio, it runs in a different process than the debugger. This means that some debugging functionality, such as breakpoints, will not work correctly.
To disable the automatic activation of the feature in SharePoint and allow proper debugging of Feature Event Receivers, set the value of the project's Active Deployment Configuration property to No Activation before debugging. Then, after your Visual Studio SharePoint application is running, manually activate the feature in SharePoint. To do this, click Site Settings on the Site Actions menu in SharePoint, click the Manage Site Features link, and then click the Activate button next to the feature and resume debugging as normal."
Source: http://msdn.microsoft.com/en-us/library/ee231550.aspx

Related

Restart Web/Api-App on Azure programmatically

How can I restart Web-Apps and API-Apps on Azure programmatically?
(I'd like to call it from another API-App within the same App service plan.)
There's also the "Microsoft Azure Management Libraries" Nuget that allows you to work with Azure services from inside of applications.
See this page for an example on how to create new web sites from inside of an Azure Web site. Restarting web services work in a similar way to creating new services. See this page for a list of available web site related methods.
Also, for authenticating is used certificate base authentication, see this page for more details on that.
Bellow is a short command line program that will restart all websites in all the webspaces you got in your Azure subscription. It works kinda like an iisreset for Azure Web Sites.
The code is based on samples taken from the links earlier mentioned:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.WindowsAzure.Management.WebSites;
using Microsoft.WindowsAzure;
using System.Security.Cryptography.X509Certificates;
using Microsoft.WindowsAzure.Management.WebSites.Models;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
var subscriptionId = "[INSERT_YOUR_SUBSCRIPTION_ID_HERE]";
var cred = new CertificateCloudCredentials(subscriptionId, GetCertificate());
var client = new WebSiteManagementClient(cred);
WebSpacesListResponse webspaces = client.WebSpaces.List();
webspaces.Select(p =>
{
Console.WriteLine("Processing webspace {0}", p.Name);
WebSpacesListWebSitesResponse websitesInWebspace = client.WebSpaces.ListWebSites(p.Name,
new WebSiteListParameters()
{
});
websitesInWebspace.Select(o =>
{
Console.Write(" - Restarting {0} ... ", o.Name);
OperationResponse operation = client.WebSites.Restart(p.Name, o.Name);
Console.WriteLine(operation.StatusCode.ToString());
return o;
}).ToArray();
return p;
}).ToArray();
if(System.Diagnostics.Debugger.IsAttached)
{
Console.WriteLine("Press anykey to exit");
Console.Read();
}
}
private static X509Certificate2 GetCertificate()
{
string certPath = Environment.CurrentDirectory + "\\" + "[NAME_OF_PFX_CERTIFICATE]";
var x509Cert = new X509Certificate2(certPath,"[PASSWORD_FOR_PFX_CERTIFICATE]");
return x509Cert;
}
}
}
Another alternative, if you can't find the function you need from the above mentioned library, you can also run powershell commands programmatically from inside of your application. You most likely will need to move, the application that is supposed to run these cmdlets, to a virtual machine to be able to load the needed powershell modules. See this page for more information on running powershell cmdlets programmatically.
You can use Powershell to do this. The relevant commands are:
Start-AzureWebsite -Name “xxxx”
Stop-AzureWebsite -Name “xxxx”
You can find help on these commands at the following links:
https://msdn.microsoft.com/en-us/library/azure/dn495288.aspx
https://msdn.microsoft.com/en-us/library/azure/dn495185.aspx
I think handling the base REST API is much better option. The Azure SDK changes quite a lot and lacks good documentation.
Here is an up-to-date sample code:
https://github.com/davidebbo/AzureWebsitesSamples/
You can adapt it to your needs.

How to hide a SharePoint tab on 100 sites? (SP2010)

I have 100 team sites in SharePoint 2010. At the last minute, I have been asked to hide a tab on each of these sites. Through the GUI, I could do this by using the Navigation option under Site Settings, but I would have to do it for all 100 sites. Is there a way to do this programmatically? Or globally through the GUI (I doubt this is an option)? I have tried using JQuery, but due to the lag, it is not a viable option. I figured there may also be the possibility to write a powershell script to do this - I am just still new to powershell.
Thoughts? Thanks.
You should use something like this in your Console application:
SPSite site = new Site("http://yoursite");
foreach (SPWeb web in site.AllWebs)
{
foreach(SPNavigationNode node in web.Navigation.TopNavigationBar)
{
if (node.Title == "Test")
{
node.IsVisible = false;
node.Update();
}
}
web.Dispose();
}
site.Dispose();
This script will hide all nodes with title "Test". You can also use Url property to determine if the node needs to be hidden.
Here I expect, that you need to change navigation of 100 child webs in site collection "http://yoursite".
P.S. Please, make sure, that you target .Net Framework 3.5 in your Console App, and AnyCPU platform is specified in Visual Studio project properties. Or you can get errors saying that your site not found.

Sharepoint get User information

I have MOSS server and users authorization is going trough AD.
I want to programmaticaly get some current user information, like e-mail, phome number.
I made the following steps:
1) create dll with [assembly: AllowPartiallyTrustedCallers]
2) i have the class PhoneBookCL that inherits System.Web.UI.WebControls.WebParts.WebPart
and I try to override CreateChildControls() for testing;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using Microsoft.Office.Server;
using Microsoft.Office.Server.UserProfiles;
using Microsoft.SharePoint;
using Microsoft.SharePoint.WebControls;
using Microsoft.SharePoint.Portal;
public class PhoneBookCL : WebPart
{
SPUser currentUser = null;
protected override void CreateChildControls()
{
try
{
SPWeb web = SPControl.GetContextWeb(Context);
currentUser = web.CurrentUser;
}
catch (Exception exp) { value = exp.Message; }
}
}
3) assigned strong name to dll, then add SafeControl to web.config:
4) dll -> to \Bin directory, added this WebPart to SP webparts collection,
added the webpart to the new Page.
Refreshing the page going to the exception: unexpected exception.
If I delete
"SPWeb web = SPControl.GetContextWeb(Context);
currentUser = web.CurrentUser;"
then all works great.
I can create Label and change its Text property and other things.
Also I tried to inherit from Microsoft.SharePoint.WebControls.WebPart, which actually inherit UI...WebPart, so the result is the same.
Maybe there is some security issue?
This problem occurs as you are deploying dll to bin. I assume your web.config has trust level as WSS_minimal . Minimal trust will not permit accessing object model.
Therefore , you have the following options:
Deploy the webpart using a wsp with custom code access security. This is slightly tedious.
Change the trust level in web.config to Full.
Deploy the dll to GAC.
From a best practices perspective, deploying the dll to bin with custom code access security will be the best option. But if you dont have security restrictions, you can look at deploying to GAC to keep things simpler.
Reference : http://msdn.microsoft.com/en-us/library/ee909485%28office.12%29.aspx
Regards,
Faiz

Sharepoint Object Model applicaton cannot run outside of WSS server

I create a C# console application using Microsoft.SharePoint object model VS WSS extensions on Windows Server 2003. The application is supposed to iterate WSS3.0 sites looking for all available lists. It runs just fine on the server. But if I try to run the exe from another computer on the network, the application crashes instantly on SPSite siteCollection = new SPSite("http://devsharepoint);
Even my try and catch doesn't help as catch is not executed.
Is it intended to run the Sharepoint object model applications only on machines with VS SharePoint extensions installed?
Here is the code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.SharePoint;
namespace ConsoleApplicationWSSobjectModel
{
class Program
{
static void Main(string[] args)
{
string url = "http://sharepoint";
Console.WriteLine("Trying to access: " + url);
try
{
SPSite siteCollection = new SPSite(url);//"http://Server_Name");
SPWebCollection sites = siteCollection.AllWebs;
foreach (SPWeb site in sites)
{
SPListCollection lists = site.Lists;
Console.WriteLine("Site: " + site.Name + " Lists: " + lists.Count.ToString());
}
Console.WriteLine("Press ENTER to continue");
Console.ReadLine();
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
}
}
You cannot use the SP object model ”outside sharepoint” you will have to use web services (or if your go with sharepoint 2010 you can use the new client object model)
Anything built with the SharePoint object model can only run on a server with SharePoint installed. There is however no dependency on the VS extensions.
You can use Client Object Model using C# or VB as your language. Add references Microsoft.sharepoint.client.dll and Microsoft.sharepoint.client.Runtime.dll it can be found under 14(SP2010) or 15(SP2013) hive ISAPI folder.

How to Create a Managed Path through SharePoint Object Model

This is a question for a WSS/SharePoint guru.
Consider this scenario: I have an ASP.Net web service which links our corporate CRM system and WSS-based intranet together. What I am trying to do is provision a new WSS site collection whenever a new client is added to the CRM system. In order to make this work, I need to programmatically add the managed path to the new site collection. I know that this is possible via the Object Model, but when I try it in my own web service, it fails. Sample code extract below:
Dim _ClientSiteUrl As String = "http://myintranet/clients/sampleclient"
Using _RootWeb As SPSite = New SPSite("http://myintranet")
Dim _ManagedPaths As SPPrefixCollection = _RootWeb.WebApplication.Prefixes
If Not (_ManagedPaths.Contains(_ClientSiteUrl)) Then
_ManagedPaths.Add(_ClientSiteUrl, SPPrefixType.ExplicitInclusion)
End If
End Using
This code fails with a NullReferenceException on SPUtility.ValidateFormDigest(). Research suggested that this may be due to insufficient privileges, I tried running the code within an elevated privileges block using SPSecurity.RunWithElevatedPrivileges(AddressOf AddManagedPath), where AddManagedPath is a Sub procedure containing the above code sample.
This then fails with an InvalidOperationException, "Operation is not valid due to the current state of the object."
Where am I going wrong?
One workaround I have managed to do is to call out to STSADM.EXE via Process.Start(), supplying the requisite parameters, and this works.
Update: whilst developing the web service, I am running it using the built-in Visual Studio 2005 web server - what security context will this be running under? Can I change the security context by putting entries in web.config?
Update: I think the problem is definitely to do with not running the web service within the correct SharePoint security context. I decided to go with the workaround I suggested and shell out to STSADM, although to do this, the application pool identity that the web service runs under must be a member of the SharePoint administrators.
Update
I think you have proved that the issue is not with the code.
SPSecurity.RunWithElevatedPrivileges: Normally the code in the SharePoint web application executes with the privileges of the user taking the action. The RunWithElevatedPrivileges runs the code in the context of the SharePoint web application pools account (i think)
The description on MSDN could go into the details a tiny bit more.
The issue with the call may be that the web service is not actually running the code within a SharePoint process, so explaining why it cannot elevate (wild guess alert).
Have a crack at changing the user of your web services application pool and see if that gives any joy.
It is likely to be a permissions issue.
Maybe try:
Dim clientSiteUrl As String = "http://myintranet/clients/sampleclient"
Using SPSite = new SPSite(clientSiteUrl)
webApp As SPWebApplication = SPWebApplication.Lookup(new Uri(clientSiteUrl));
If Not (webApp.Prefixes.Contains(clientSiteUrl)) Then
webApp.Prefixes.Add(clientSiteUrl, SPPrefixType.ExplicitInclusion)
End If
End Using
This is not exact code.
Since the above code is not the exact code, here is the exact working code for a Web Application scopped feature in the Feature Activated event:
On feature activation at the Mange web application features page, activate feature will create a new Explicit managed path in the specified web application (I want to replace the hard coding, maybe with Properties.Feature.Parent, or something similar.)
using (SPSite site = new SPSite("http://dev-moss07-eric/PathHere")) {
SPWebApplication webApp = SPWebApplication.Lookup(new Uri("http://dev-moss07-eric"));
if (webApp.Prefixes.Contains("PathHere"))
{
//
}
else
{
webApp.Prefixes.Add("PathHere", SPPrefixType.ExplicitInclusion);
}
}
Code can probably be improved, but its my attempt at converting the above code.
If you want to create a managed path (explicit) and a site collection at that path, do the following:
using (SPSite site = new SPSite("http://dev-moss07-eric")) {
SPWebApplication webApp = SPWebApplication.Lookup(new Uri("http://dev-moss07-eric"));
if (webApp.Prefixes.Contains("ManagedPathHere"))
{
//
}
else
{
webApp.Prefixes.Add("ManagedPathHere", SPPrefixType.ExplicitInclusion);
}
using (SPWeb web = site.OpenWeb())
{
SPWebApplication webApplication = web.Site.WebApplication;
try
{
webApplication.Sites.Add("ManagedPathHere","Site Title Here","This site is used for hosting styling assets.", 1033, "STS#1", "6scdev\\eric.schrader", "Eric Schrader", "eric.schrader#6sc.com");
}
catch (Exception ex)
{
//ex.ToString;
}
}
}

Resources