Change XSLT of the SearchResultWebPart during the FeatureActivated - search

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.

Related

Export to Excel from grid - no data

I am getting an Excel spreadsheet with columns but, no data when I click on the Excel icon on a grid.
I have put a grid on the CR306030 page that is tied to a view of a custom DAC that relates back to the CRActivity record for the page. I have set the SkinID to Inquire and the AllowImport = true. The view in my Graph extension class looks like this:
[PXImport(typeof(CRActivity))]
public PXSelect<MyDac,
Where<MyDac.activityNoteID,
Equal<Current<CRActivity.noteID>>>> MyDacView;
I'm not sure what I am missing. I am trying to export the data in the grid so, I may be way off here.
TIA!
This happened because I had an update() call inside of a FieldSelecting() event handler. This, for some reason, caused the export to quit working. This presents another problem for me that I will post in another question but, the export issue is resolved. Here's what my code looked like in the extended graph that was causing the issue:
protected virtual void CRActivity_UsrCustomField_FieldSelecting(PXCache cache, PXFieldSelectingEventArgs e)
{
CRActivity activity = (CRActivity) e.Row;
CRActivityExt activityExt = activity.GetExtension<CRActivityExt>();
// Some code here.
e.ReturnValue = TotalValue;
activityExt.UsrCustomField = TotalValue;
Base.Events.Update(activity);
}
I changed it to this in order to get the export working:
protected virtual void CRActivity_UsrCustomField_FieldSelecting(PXCache cache, PXFieldSelectingEventArgs e)
{
CRActivity activity = (CRActivity) e.Row;
CRActivityExt activityExt = activity.GetExtension<CRActivityExt>();
// Some code here.
e.ReturnValue = TotalValue;
//activityExt.UsrCustomField = TotalValue;
//Base.Events.Update(activity);
}
Adding Export button is all that should be required. Setting SkinID to inquire will do that for you.
It seems you are running into an uncommon scenario so I would suggest to rollback tentative solutions like adding Import functionality that isn't required in case your implementation has errors causing conflicts with export functionality.
Next issue I would suspect is a kind of security/rights issues or an explicit call to disallow exporting records. Removing unnecessary code and substituting the DAC you are using could help expose the root cause as some specific entity could have been locked down by security while others aren't.
If you're familiar with Acumatica web services it could be worth a shot to test if records from the grid can be retrieved by web service. If they can't then that points towards security/rights issues.

Reuse web agents that PRINT to the browser in XPages Lotus

When upgrading classic Domino applications to XPages one particular problem arises constantly: "what to do with the PRINT statements in existing agents that write back directly to the browser?" I have 200 agents in my nsf file which all uses Print statement in their code.
I have investigated found the link http://www.wissel.net/blog/d6plinks/SHWL-8SF7AH
but it is not possible for me to change agent code as it is also used from forms.
I have to re-use these agents from xpages on button click and also have to pass document.
Is there any way or alternative which can solve my problem.
help is required.
We have Agent.runWithDocumentContext(doc:NotesDocument) method which can run the agent from xpage and passing an in-memory document. I create an im-memory document
var doc = database.createDocument();
doc.replaceItemValue("StartDate",startDate.getDateOnly())
doc.replaceItemValue("EndDate",endDate.getDateOnly())
doc.replaceItemValue("ReportName",reportName)
var agent:NotesAgent = database.getAgent("("+reportName+")");
agent.runWithDocumentContext(doc);
This in-memory document i can pass to the agent. But the issue I am facing currently that my agents are used to print directly which is not possible through xpage i assume.
Is there any alternative way to pass in-memory document to agent and able to print directly to browser through xpages.
Help needed please help.
If you want to use XPages.. then USE XPages... Meaning migrate the agents to the XPages way of doing things. There can be a lot of coexhistance between XPages and Notes Client or I supposed even Classic Domino Web. But if you're set on keeping 200 Agents which are NOT really part of XPages Best practices, then it sounds to me like you shouldn't be using XPages at all.
EDIT:
This link:
http://www-10.lotus.com/ldd/ddwiki.nsf/dx/XPages_and_Calling_Agents_Using_an_In-Memory_Document
Talks about calling an Agent from XPages and being able to use the in memory document. Maybe that will help but if it's heavily used performance will not be great since an agent loads and unloads for each call. It's still a bad idea to do.
create a java class that calls your agent and read the output from your agents in an input stream and display the stream in computed field in Xpages.
here is a sample java class that will retrive the output from your agent
package com.thomas;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.MalformedURLException;
import java.net.URL;
public class getAgentData{
public String getData() throws IOException {
try {
URL url = new URL("http://localhost/mydatabase.nsf/myagent?openagent");
BufferedReader in = new BufferedReader(
new InputStreamReader(url.openStream()));
String content = new String();
String inputLine;
while ((inputLine = in.readLine()) != null) {
content+=inputLine;
}
in.close();
return content;
} catch (MalformedURLException e) {
e.printStackTrace();
}
return null;
}
}
If you add your java class as a bean in faces-config.xml you can call it using a computed field in your xpages like this
<xp:text escape="true" id="computedField1" value="#{javascript:getAgentData().getData()}"></xp:text>
You need to change your agent a little. Instead of Print "Something" you would use someobj.print "Something" - which should be a manageable task using search/replace. The detailed steps have been documented in this blog entry.
Now you state that you need to dual use the agent. Not that hard, once you move beyond copy and paste programming.
When you check the class - it looks for documentcontext. When you call the agent directly, the document context is not there. So you check if you have the document - if not it is classic and you add a print statement to the class, if it is there you save to the context.
The code is myObject.printResult = true to print - or you set it to true per default (but then you pollute your log :-) )
If you provide a context doc when calling the agent, then you would provide an item (e.g. DontPrint=1) from your XPages and check that one. If it is there, only save to the context, otherwise add the print statement.
Let us know how it goes.

Dynamics AX 2012 - Custom Lookup in a dialog

So, I am working on a class called DMFWriteExportData and trying to get it run in Batch.
I am at a point where I need to figure out a way to get rid of fieldControl and the reason being it does not let me Run the class on the server and throws an error because it is not supposed to be running on server? (not sure)
Error: "The method Dialog Control.control cannot be called from the server; use methods on the Dialog Field class instead."
-
public Object dialog()
{
DialogRunbase dialog = new DialogRunbase("#DMF372", this);
FormStringControl control;
dialogExecution = dialog.addFieldValue(extendedTypeStr(dMFExecutionId), executionId);
control = dialogExecution.fieldControl();
control.mandatory(true);
control.displayLength(24);
control.registerOverrideMethod(methodstr(FormStringControl, lookup), methodstr(DMFWriteExecutionParameters, executionIdLookup), this);
control.registerOverrideMethod(methodstr(FormStringControl, modified), methodstr(DMFWriteExecutionParameters, executionIdModified), this);
dialogdescription=dialog.addFieldValue(extendedTypeStr(description),DMFExecution::find(executionId).Description);
dialogdescription.enabled(false);
return dialog;
}
I am wondering:
If it is actually true that this class cannot be set to server
when using control.registerOverrideMethod
If yes, what would be the ideal solution to overcome this situation,
is there any way I can create custom lookups? I see there is method
called registerOverrideMethod in the DialogField class.
Any help would be appreciated.
Thanks,
Khosla
The reason why you cannot (and should) run the code above in batch is because it uses dialog controls that only exist on the client side. You should never run this kind of code on server. Please check runon property of your class and set it to called from.
However, I assume you are using RunBaseBatch. If you are on AX 2012, you should use the SysOperation framework instead.
When using RunBaseBatch, all code is on the same class. This way, you are mixing client side code (main method, dialog method etc) with the code that should run on server (run method). For this reason you should set the "runon" property of the class to CalledFrom, not Server.
You can solve this by using SysOperation which applies the Model View Controller (MVC) pattern that neatly sepperates the two.
For an introduction to SysOperation, check my blog here:
AX2012: SysOperation introduction

trust set to Full, but web part still causes SecurityException

I've got a web part that accesses the SP object model, packaged in an assembly which is signed and deployed to the GAC. The web.config is set for "Full" trust, and yet my web part throws a SecurityException. The offending lines of code:
SPSecurity.RunWithElevatedPrivileges(new SPSecurity.CodeToRunElevated(() =>
{
foreach (SPGroup g in user.Groups)
{
identity += String.Format(",'{0}'", g.Name.ToLowerInvariant().Replace(#"\", #"\\"));
}
}));
It appears that the exception is thrown when RunWithElevatedPrivileges is called (in other words, my delegate doesn't execute at all). Any ideas? I'm completely bewildered at this point.
update: here's what the code looked like before I wrapped it in the RunWithElevatedPrivileges method:
public MyWebPart()
{
context = new MyProject.Data.MyDataContext(ConfigurationManager.ConnectionStrings["MyDB"].ConnectionString);
SPUser user = SPContext.Current.Web.CurrentUser;
identity = String.Format("'{0}'", user.LoginName.ToLowerInvariant().Replace(#"\", #"\\"));
foreach (SPGroup g in user.Groups)
{
identity += String.Format(",'{0}'", g.Name.ToLowerInvariant().Replace(#"\", #"\\"));
}
identity = '[' + identity + ']';
}
And the exception:
System.Security.SecurityException occurred
Message="Request failed."
Source="Microsoft.SharePoint"
StackTrace:
at Microsoft.SharePoint.SPBaseCollection.System.Collections.IEnumerable.GetEnumerator()
at MyProject.MyWebPart..ctor()
InnerException:
Based on the highlight provided by the exception helper, it looks like the attempted access of the SPUser.Groups property is the problem: user.Groups.
What's got me really confused is that this exact code was working fine two days ago, but I had some other problems with the farm and basically had to rebuild it. After getting everything else back up again, I went and tried to add this web part to a page and this problem manifested itself. I tried wrapping the code in the RunWithElevatedPrivileges wrapper to see if I could isolate exactly the offending bit, but it looks like anything that touches the SP oject model causes the exception, including the RunWithElevatedPrivileges method.
update2: I still don't know the real reason this was failing, but it was happening when I was trying to add the web part. After setting breakpoints in the debugger, I realized that the constructor was being called twice; the first time, it all worked exactly as expected, but the second time was when the exception was being thrown. I still have no idea why. I found two ways around this: move the offending code out of the constructor into a later point in the lifecycle of the web part, or comment out the code to add the web part, then uncomment it and redeploy.
Apparently, the reason this "worked 3 days ago" was because I had added my web part to a page a long time ago, and then added the above code to the constructor. Since the web part was already added, I never saw any problems. Later, when I recently had to rebuild the site and add the web part to the page again, this problem manifested itself. So technically, it didn't "work" before, I just wasn't doing the thing that made it misbehave.
Anyway, like I said - I still don't know the true cause of the exception, so answers along those lines are still welcome.
The problem could occur if you try to work with SharePoint objects which were created outside of the RunWithElevatedPrivileges() method, and therefore still hold their old security context. In your case you use a SPUser object which was not created within the RunWithElevatedPrivileges() method.
To work around, you should create the object you want to work with within the delegate. Safe Ids or URLs outside of the delegate, to use them for recreating the objects. E.g.: safe the URL or ID of a SPSite object and use it to create it again within the delegate.
public void Demo()
{
string siteURL = SPContext.Current.Site.Url;
SPSecurity.RunWithElevatedPrivileges(delegate(){
using (SPSite safeSite = new SPSite(siteURL))
{
// place your code here ...
}
});
}
Perhaps you could post the stack trace so we can get some more information.

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