How to retrieve data from an XML file in a Sharepoint 2010 Feature Event Receiver? - sharepoint

I am following this tutorial and I am trying to setup the code in a Event Receiver.
I need 2 properties to send into their method a SPWeb and string.
public override void FeatureActivated(SPFeatureReceiverProperties properties)
{
// is there a way to make this non hardcoded?
SPSite site = new SPSite("http://localhost.com");
SPWeb web = site.OpenWeb("/");
string XMlPath = // get xml file path
CreateGroups(web, path);
}
private void CreateGroups(SPWeb currentSite, string groupsFilename)
{
}
So I tried to use getFullPath but that did not work. I also tried to use MapPath but I did not seem to have access to that.
So how do I get XML file (I think thats what I need)?

You need to dispose of the SPSite / SPWeb object, this is usually done in a using clause.
You don't need to use an absolute path (hard code) in a feature receiver, as the feature is already web/site scoped
your XmlPath usually needs to point to a file on the Sharepoint server, which you also deployed in your Feature - as the feature receiver is running after all the normal files have been deployed, you're good.
Without further ado, slightly different code:
public override void FeatureActivated(SPFeatureReceiverProperties properties)
{
//Web scoped feature?
//spWeb = (SPWeb) properties.Feature.Parent;
//assuming Site scoped feature
spWeb = ((SPSite) properties.Feature.Parent).RootWeb;
using (spWeb)
{
string XmlPath = properties.Definition.RootDirectory + #"\Xmlfile\groups.xml"
CreateGroups(spWeb, XmlPath);
}
}
So how do you get your XML file into "\Xmlfile\groups.xml"? Just create a module! (Add new item > Module)
The elements.xml of your module should look something like this:
<?xml version="1.0" encoding="utf-8"?>
<Elements xmlns="http://schemas.microsoft.com/sharepoint/">
<Module Name="Xmlfile" Path="Xmlfile">
<File Path="groups.xml" Url="Xmlfile/groups.xml" />
</Module>
</Elements>
Of course you will need to add your groups.xml file into that module (Context menu > Add existing item) for this to work.
Also note that you can easily debug feature receivers, just make sure that the deployment configuration is set to "No Activation" (Project Properties > Sharepoint > Active Deployment Configuration) - this way you will need to manually activate the feature on the site (instead of Visual Studio doing it automatically for you in debug mode) - but debugging will work flawlessly.

Related

How to get Liferay Authverifer working

I am implementing Liferay 6.2 AuthVerifier. I developed it but it does not get called that is, TestAuthVerifier.verify() method.
I referred https://docs.liferay.com/portal/6.2/propertiesdoc/portal.properties.html the link to develop tthe est AuthVerifer. Here is what I do below
I make entries in portal-ext.properties file as below and develop the class further.
auth.verifier.pipeline=com.test.TestAuthVerifier
auth.verifier.TestAuthVerifier.version.supported=1.0
my code is as below just for reference.
package comt.test;
import com.liferay.portal.security.auth.*;
public class TestAuthVerifier implements AuthVerifier {
#Override
public String getAuthType() {
return PhAuthVerifier.class.getSimpleName();
}
#Override
public AuthVerifierResult verify(
AccessControlContext accessControlContext, Properties properties)
throws AuthException {
System.out.println("MyAuthVerifier.verify() invoked..")
try {
.....
return authVerifierResult;
} catch (AutoLoginException e) {
throw new AuthException(e);
}
}
On debugging from Liferay 6.2.3 source code I see the point when
the flow is broken is AuthVerifierPipeline._mergeAuthVerifierConfiguration() method.
the statement : Map settings = accessControlContext.getSettings(); returns zero size map.
Finally the actual place where the Verifier is called : AuthVerifierPipeline._verifyRequest() does not run as List authVerifierConfigurations is ZERO size.
I looked in AccessControlContext class and other classes, I could not see any setter method to set _settings or any references which set this var.
any help around this is much appreciated.
note : I verified that LifeRay does recognize my TestAuthVerifier impl.
to make it work you have to work with the hook plugin. First create a file liferay-hook.xml in WEB-INF folder to override the portal.properties
<?xml version="1.0"?>
<!DOCTYPE hook PUBLIC "-//Liferay//DTD Hook 6.2.0//EN" "http://www.liferay.com/dtd/liferay-hook_6_2_0.dtd">
<hook>
<portal-properties>portal.properties</portal-properties>
</hook>
In the src folder put the file portal.properties or if you are using maven in the resource folder with the properties of the AuthVerifier in your case
auth.verifier.pipeline=com.test.TestAuthVerifier
auth.verifier.TestAuthVerifier.version.supported=1.0
This is a link of a sample in liferay git for more detail sample-authverifier-hook

TFS and MSBuild projects Logging for each project

I'm going build large number (300+) of projects on TFS. I'm considering a proj file to manage these as follows:
<ItemGroup Label="GGX_Projects" >
<MyProj Include="$(Source)Proj1.vcxproj" />
<MyProj Include="$(Source)Proj2.vcxproj" />
<MyProj Include="$(Source)Proj3.csproj" />
<MyProj Include="$(Source)Proj4.csproj" />
<MyProj Include="$(Source)Proj5.vcxproj" />
<MSBuild Projects="#(MyProj)"
Targets="ReBuid"
Properties="Configuration='$(Configuration)'"
RebaseOutputs="true"
ContinueOnError="true"
/>
This actually working fine, but one thing I'm unable to achieve i.e. to get Log for each of the projects mentioned in ItemGroup.
I need separate logs, so that if any project fails, that log can be sent via e-mail.
In addition, on msbuild command line, I tried /distributedFileLogger, but unable to understand how to use this to get log file for each project separately.
Is that a correct approach?
Can anyone please suggest some better solution which could provide separate logging for each project??
Distributed file logger is, as the name suggests, for logging from individual MSBuild nodes within a "distributed" build system, not for logging from individual projects, targets or tasks. You can try creating a simple custom logger, it is fairly trivial, I've written a sample below. Although, you might want to play around with event types for verbosity and use something like NLog rather than appending to files as you might get locks.
msbuild PerProjectLogger.sln /logger:PerProjectLogger\bin\Debug\PerProjectLogger.dll
using System.Collections.Concurrent;
using System.IO;
using Microsoft.Build.Framework;
namespace PerProjectLogger
{
public class Logger : Microsoft.Build.Utilities.Logger
{
public override void Initialize(IEventSource eventSource)
{
var loggers = new ConcurrentDictionary<string, FileInfo>();
eventSource.AnyEventRaised += (s, a) =>
{
var property = a.GetType().GetProperty("ProjectFile");
if (property == null)
return;
var project = property.GetValue(a) as string;
if (project == null)
return;
var logger = loggers.GetOrAdd(Path.GetFileName(project), name => new FileInfo(name + ".log"));
using (var writer = logger.AppendText())
writer.WriteLine(a.Message);
};
}
}
}
The simplest way to achieve this with TFS is to create a single build detention and then on the Process tab you should see an option to pick solutions to build. Here you can add each Project individually. When you do a build the default build process will do a foreach project and build them. You will get a log file in the drop location for each project.

How to create a ReSharper 8.X Custom Macro that can fetch and process the containing type name

ReSharper 8.X ships with a macro that fetches the "Containing Type Name", but what I want to do is manipulate that name. I'm using this in a Visual Studio 2013 Web API project, and I want a template that takes the class name and builds the URL that has to be called. So, for example, suppose I have this:
public class AnnouncementController : ApiController
{
//Want to put a template here!
[HttpGet]
public HttpResponseMessage GetActiveAnnouncements()
{
/// ...
}
}
now my ReSharper template will look something like this:
/// This sample shows how to call the <see cref="$METHOD$"/> method of controller $CLASS$ using the Web API.
/// https://myurl.mydomain.com/api/$CONTROLLER$/$METHOD$
$Controller$, by convention, is the class name minus the letters 'Controller'. This is because ASP.NET MVC Web API projects expect classes derived from ApiController to end with the string 'Controller',
Since this class is AnnouncementController, the template should output
https://myurl.mydomain.com/api/Announcement/GetActiveAnnouncements
Resharper's Built-In Macros can give me some of what I need, but I want to write a custom macro that fetches the containing type name and chops "Controller" off of it. I would like to do that directly, without storing the containing type name in another parameter.
Also, how do I install this custom macro? I've Googled around, and all I found was a lot of dead links and old walkthroughs written for ReSharper version 7 and below that do NOT work with ReSharper 8.x
After a lot of fighting, here is my solution.
[MacroImplementation(Definition = typeof (ControllerNameMacroDefinition))]
public class ControllerNameMacroImplementation : SimpleMacroImplementation
{
public ControllerNameMacroImplementation([Optional] IReadOnlyCollection<IMacroParameterValueNew> arguments)
{
}
public override HotspotItems GetLookupItems(IHotspotContext context)
{
var ret = "CONTROLLER";
var fileName = GetFileName(context);
if (!fileName.IsNullOrEmpty())
{
//Replace "Controller.cs" in two separate steps in case the extension is absent
ret = fileName.Replace("Controller", "").Replace(".cs", "");
}
return MacroUtil.SimpleEvaluateResult(ret);
}
/// <summary>
/// Returns the filename of the current hotspot context
/// </summary>
private string GetFileName(IHotspotContext context)
{
var psiSourceFile = context.ExpressionRange.Document.GetPsiSourceFile(context.SessionContext.Solution);
return psiSourceFile == null ? string.Empty : psiSourceFile.Name;
}
}
I wanted to do exactly this, but for JavaScript Jasmine tests -- SomethingViewModel.js, with a fixture of SomethingViewModelFixture.js, but wanted to be able to refer to SomethingViewModel in the file. A few slight modifications to the above made it possible.
Unfortunately, there's a ton more things you need to do in order to get your plugin to actually install. Here's a list. I hope it's comprehensive.
NuGet package install JetBrains.ReSharper.SDK, make sure you have the correct version installed!
Copy your Class Library DLL to C:\Users\<you>\AppData\Local\JetBrains\ReSharper\<version>\plugins\<your plugin name>, creating the plugins directory if needed.
You need the plugin Annotations in your AssemblyInfo.cs file:
[assembly: PluginTitle("Your extensions for ReSharper")]
[assembly: PluginDescription("Some description")] -- this is displayed in ReSharper->Options->Plugins
[assembly: PluginVendor("You")]
You need a class in your project that defines the MacroDefinition, as well as the above MacroImplementation
[MacroDefinition("MyNamespace.MyClassName", ShortDescription = "A short description of what it does.", LongDescription = "A long description of what it does.")]
"ShortDescription" - this is displayed in the "Choose Macro" dialog list.
"LongDescription" you'd think this would be in the "Choose Macro" description, but it isn't.
I just added this annotation to the above file.
The file you add the MacroDefinition to needs to implement IMacroDefinition, which has a method (GetPlaceholder) and a property (Parameters) on it. The former can return any string ("a") and the latter can return an empty array.
You can ignore the WiX/NuGet stuff if you want. Just for a local install.
In VS, the ReSharper->Options->Plugins section has some troubleshooting details on why your plugin might not be loading.
Good luck!

Change XSLT of the SearchResultWebPart during the FeatureActivated

I have a piece of code which changes XSLT of a SearchResultWebPart at Sharepoint 2010 Search Center result page (spFileItem - is SPFile of a search result page) :
SPLimitedWebPartManager wpManager = spFileItem.GetLimitedWebPartManager(PersonalizationScope.Shared);
foreach (WebPart wpItem in wpManager.WebParts)
{
if (wpItem is CoreResultsWebPart)
{
((CoreResultsWebPart)wpItem).UseLocationVisualization = false;
((CoreResultsWebPart)wpItem).Xsl = someXSL;
wpManager.SaveChanges(wpItem);
}
spFileItem.Update();
spFileItem.CheckIn(Consts.CheckInComment, SPCheckinType.MajorCheckIn);
But, this code doesn't work if it is called on feature activated (gives InvalidOperationException - incorrect object state). However it perfectly works in Console application.
After some reflecting, I found out that there is a piece of code inside the SearchResultWebPart, which checks if the webpart wasn't initialized - it throws the mentioned above exception on setting XSL property. Does anybody know how to work this problem out? For me it'd be quite convenient to do XSL change at FeatureActivated...
I found a solution to my problem, but it uses different way of setting xsl for SearchResultBaseWebPart.
SPLimitedWebPartManager wpManager = spFileItem.GetLimitedWebPartManager(PersonalizationScope.Shared);
foreach (WebPart wpItem in wpManager.WebParts)
{
if (wpItem is CoreResultsWebPart)
{
((CoreResultsWebPart)wpItem).UseLocationVisualization = false;
((CoreResultsWebPart)wpItem).XslLink = spFileItem.Web.Url + #"/_layouts/XSL/MYXSL.xsl";
wpManager.SaveChanges(wpItem);
}
}
spFileItem.Update();
spFileItem.CheckIn(Consts.CheckInComment, SPCheckinType.MajorCheckIn);
I feel you mix up a few things in the question. You would like to set the Xsl property of the CoreResultsWebPart. This class has no direct implementation of the Xsl method, so it inherits the implementation of its parent class (SearchResultBaseWebPart). The Xsl property setter try to set the XslHash property (but only if we are after the OnInit that sets _BeforeOnInit = false;), and the setter method of the XslHash property throws an InvalidOperationException, but this exception should be catched by the try/catch block in Xsl property setter anyway. I don't see any other potential source of InvalidOperationException in the code.
You should check the patch level of your SP2010 (is it SP1/some of the cummulative updates/original version?) and try to activate the feature from different contexts (from web site / STSADM or PowerShell).
But first I suggest you to add a try / catch block to your feature receiver code and trace out the error details (like stack trace) and monitor the results using DebugView.

Sharepoint Smartpart Issue

I am very new to Sharepoint programming, like the rest of my team is. We have decided to use smart part as our bridge between sharepoint and our development efforts. After some effort we got it up and running. However, the problem is, that when i use a simple user control for test, with sharepoint om code that gets names of files in a document library, sharepoint gives me a rather helpful "An unknown error has occured". This code works just fine when inside an aspx page. I have written another simple test user control that just executes a Response.Write() line to check is there a problem with executing code, but this one works just fine in smart part too.
Code goes like
protected void Button1_Click(object sender, EventArgs e)
{
Microsoft.SharePoint.SPSite srv1 =
new SPSite("http://server:port/");
SPWeb web = srv1.OpenWeb();
var list = web.GetFolder("http://server:port/documentLibrary");
for (int i = 0; i < list.Files.Count; i++)
{
ListBox1.Items.Add(list.Files[i].Name);
}
}
Anything we may be missing or doing wrong?
Many thanks in advance...
AFAIK, Smart Part hasn't been really needed since SharePoint 2003. Why don't you just create a regular user control and plop it in the /ControlTemplates folder? Deploy it is as part of a Feature with related code, if appropriate...
Also, update your Web.Config file to display meaningful error messages:
customErrors=off
Enable Stack Traces by adding CallStack=”true” to the SafeMode tag
Set the compilation debug attribute to "true"
Just a side note, you should generally wrap your SPSite and SPWeb objects in a using clause as these are unmanaged objects as outlined here:
http://msdn.microsoft.com/en-us/library/aa973248.aspx
protected void Button1_Click(object sender, EventArgs e)
{
using (Microsoft.SharePoint.SPSite srv1 = new SPSite("http://server:port/"))
{
using (SPWeb web = srv1.OpenWeb())
{
var list = web.GetFolder("http://server:port/documentLibrary");
for (int i = 0; i < list.Files.Count; i++)
{
ListBox1.Items.Add(list.Files[i].Name);
}
}
}
}
Ok it's solved, thanks everybody for information and help.
It was about trust level and i set thrust level to "WSS_Medium" in relevant site collection's web.config file.
<trust level="WSS_Medium" originUrl="" />
I have found this solution (along with some more relevant information on subject) in Jan Tielen's blog at here

Resources