I have an aspx page with inline code in which I am trying to update the view programmatically by setting view's Query property to my CAML query. When I run with administrator user everything works perfect view get updated successfully but when I logged in with a user who belongs to visitor group and having read only access then I get an error on view.Update() line saying that:
"Unable to evaluate expression because the code is optimized or a native frame is on top of the call stack"
I have already try to run this code block with ElevatedPrivileges but not get any luck...(
following is my code which make you more clear:
SPUserToken token = CurrentSite.SystemAccount.UserToken;
using (SPSite st=new SPSite(SPContext.Current.Web.Url,token))
{
st.AllowUnsafeUpdates = true;
using (SPWeb wb=st.OpenWeb())
{
wb.AllowUnsafeUpdates = true;
vwSearchResult.Query = Query;
vwSearchResult.Update();
}
}
What you are doing here, is modifying the definition of the view for ALL users of the website, not only the current rendering instance of the page. This is why simple visitors cannot change it (they do not have such permission in the web)
If you want to do something, using the "SystemAccount" token, you have not only to do the "using SPSite, using SPWeb", but also find the list and the view using the "strong" SPWeb objects
Instead of modifying a view definition at runtime, you might want to consider using ListViewByQuery class http://msdn.microsoft.com/en-us/library/microsoft.sharepoint.webcontrols.listviewbyquery.aspx
Related
Has anyone found a way to automatically add a jslink URL to lists by default instead of having to add the URL to every list manually when they are created? Ultimately we'd like to have default jslink for each type of app the editors have access to.
yes, this was described perfectly by Chris O'Brien here: http://www.sharepointnutsandbolts.com/2013/01/using-jslink-to-change-ui-of-sharepoint_20.html
short story - you should create list template and define jslink there, so all lists based on this template would have the js link. If you don't want to assosiate lists with templates by any reason, you should look into event receivers. (for List created event.)
Another solution is to write your own code to update all of your pages.
On this page Tobias Zimmergren shows a code updating JSLink with PowerShell:
PowerShell: Configure the JSLink property of a Web Part
I personally use C# CSOM to update JSLink on all requested pages.
Here is the sample code which updates JSLink on one page (for simplicity I have stripped out exception handling and all non-happy-path logic):
using Microsoft.SharePoint.Client;
using Microsoft.SharePoint.Client.WebParts;
void UpdateWebPart(ClientContext webpartContext, string RelativeUrl, string JSLink)
{
File page = webpartContext.Web.GetFileByServerRelativeUrl(RelativeUrl);
LimitedWebPartManager wpm = page.GetLimitedWebPartManager(PersonalizationScope.Shared);
webpartContext.Load(page);
webpartContext.Load(wpm.WebParts, wps => wps.Include(w => w.WebPart.Title, w => w.WebPart.Properties));
webpartContext.ExecuteQuery();
if (wpm.WebParts.Count > 0)
{
// You can find your WebPart inside wpm.WebParts e.g. by Title. On each page I have only 1 WebPart, so I just take the first.
WebPartDefinition wpd = wpm.WebParts[0];
WebPart myWP = wpd.WebPart;
if ((string)myWP.Properties["JSLink"] != JSLink)
{
myWP.Properties["JSLink"] = JSLink;
wpd.SaveWebPartChanges();
webpartContext.ExecuteQuery();
}
}
}
webpartContext is SharePoint ClientContext created earlier
RelativeUrl is something like: "/Lists/Sample%20Tasks/AllItems.aspx"
JSLink is new value for JSLink of WebPart, which you want to update
I have custom application with active use of CRM lookups.
I can open CRM lookup from my JS like this:
function OpenLookup() {
var url = "http://CRM_SERVER_NAME/ORG/_controls/lookup/lookupsingle.aspx?class=null&objecttypes=2&browse=0&ShowNewButton=0&ShowPropButton=1&DefaultType=0";
var lookUp = window.showModalDialog(url, "entity",..);
...
}
How can I setup customView on lookup (typically it can be done using addCustomView(..) but I can't call any CRM Javascript (no CRM Javascript model on my form). Is this any way to do this?
I'm perfectly happy with any unsupported method.
Just a silly (or not) idea.
The lookup comes from an existing entity form so … why not open this CRM form (the inner IFRAME edit.aspx not the main.aspx) inside an IFRAME (hidden, resized) in your custom application ,wait until it loads and open the lookup from inside this IFRAME. This way you have access to the entire Xrm.Page model including addCustomView. You may also attach to this lookup field change event to get the selected value.
To make the IFRAME load fast you can create a new role form with only the lookup/s you need to pop and use this in your IFRAME.
I'm trying to make a site map for a Sharepoint 2010 that will list every site and that site's current nav items. Navigation between sites is done via the top nav. However, I'm having problems getting the current nav items for each site. It appears that each time I get the PortalSiteMapProvider for the web, it returns the provider for the whole site collection. How do I get the items for just that site? I run this code for each site I want to get the items for:
var provider = new PortalSiteMapProvider();
provider.NavigationType = PortalNavigationType.Current;
provider.CurrentWeb = web;
var rootNode = provider.RootNode;
Anyone have any idea where to go from here?
EDIT:
So it isn't possible to just access each site collection and run this code. The PortalSiteMapProvider doesn't allow it. It is, however, possible to run this code in a ashx that's located in the layouts folder. I just need to access that ashx file from the site collection I want to enumerate, and it will work just fine :)
private void DrawWeb(SPWeb web, TreeNode node)
{
SPWebCollection webCol = web.Webs;
foreach (SPWeb w in webCol)
{
var n = new TreeNode(w.Title);
node.ChildNodes.Add(n);
DrawWeb(w, n);
w.Dispose();
}
}
Try calling this method like:
TreeNode webNode = new TreeNode(rootNode.Title);
DrawWeb(provider.CurrentWeb, webNode);
Hope this will be helpful.
So it isn't possible to just access each site collection and run this code. The PortalSiteMapProvider doesn't allow it. It is, however, possible to run this code in a ashx that's located in the layouts folder. I just need to access that ashx file from the site collection I want to enumerate, and it will work just fine :)
I have not worked with webparts for sharepoint before, but need to make change to a webpart, that needs to be propagated to some 700 websites. It is a change to one of the properties of the webpart, the value needs to be changed. Is there a way to get metadata for a webpart and change it directly in the database (I assume that is where it is stored.)?
Here is the scenario: Webpart contains a comma delimited list of document types (internal type) that it should display. Now there are new doc. types that need to be added to all 700 websites. I need a way to enumerate websites, get the webpart metadata, and add these new doc types to webpart. Currently they go manually to each website, click on edit, type in new doc type, and save it.
As others have said the correct approach is to programmatically achieve this rather than edit the content database which will make your installation unsupportable. I regularly use a console application to do this in a site collection made up of sites created from a site template.
Here is an example that changes the Title property of a ListViewWebPart. Updated to include code for recursive loop. I haven't tested this but it should work.
private static void ProcessSiteCollection(string url)
{
using (SPSite siteCollection = new SPSite(url))
{
SPWeb rootWeb = siteCollection.RootWeb;
ProcessWebs(rootWeb);
}
}
private static void ProcessWebs(SPWeb parentWeb)
{
foreach (SPWeb web in parentWeb.Webs)
{
try
{
UpdateWebPart(web); // Set web part properties
ProcessWebs(web); // Recursively loop through children
}
finally
{
web.Dispose();
}
}
}
private static void UpdateWebPart(SPWeb web)
{
using (SPLimitedWebPartManager webPartManager =
web.GetLimitedWebPartManager("default.aspx", PersonalizationScope.Shared))
{
try
{
foreach (WebPart webPart in webPartManager.WebParts)
{
if (webPart.Title == "My Web Part")
{
ListViewWebPart listViewWebPart = (ListViewWebPart)webPart;
listViewWebPart.Title = "Updated Web Part";
webPartManager.SaveChanges(listViewWebPart);
web.Update();
break;
}
}
}
finally
{
webPartManager.Web.Dispose();
}
}
}
Directly accessing the sharepoint content databases is a big "no no." That's the official answer. :)
That being said, I have only ever looked in the content databases and never tried to actually change anything manually.
My suggestion, would be to modify the existing web part to modify the property based on currently set property(s). (I am assuming that some currently set property is invalid or needs to be updated based on changes to the infrastructure.) ... If this is the case, you can validate the property; making sure that current property is changed to what it needs to be, and/or making sure future property changes are valid.
Good luck!
DON'T
Seriously, do not go into the content databases and edit it. That way you are not supported anymore if anything should happen and Microsoft will not support you anymore (not until you revert the database back to an earlier version from a backup that is).
You can use the API to access webparts in your sites, here's some code that should get you started:
Enumerate page webparts
If anyone is having idea how to customize properties in a smartpart. I have created usercontrol and i m wrappin it in a smartpart.I want to upload my xml from Document library.
private string feedXML;
[Browsable(true),
Personalizable(true) ]
public string FeedXML
{
get
{ return feedXML; }
set
{ feedXML = value; }
}
and I am using this like
//
feedXML="\customxml.xml";
XPathDocument doc = new XPathDocument(Server.MapPath(feedXML));
but this thing is not working . When I am clicking on modify shared webpart of sharepoint page is not rendering. Any clue where I m getting wrong.
You might want to verify the result of your server.mappath statement. It will be something like C:\Inetpub...
So your code is trying to retrieve a file from the filesystem that really lives in SharePoint because you have uploaded it to a Document Library.
If you want that file you'll have to retrieve it using the SharePoint object model, have a look at the GetFileAsString method.
I agree with Denni..
Seems like Smartpart is only making it more difficult? What advantages does it have?
I make my own webpart containers for ascx controls.. very little work and all the control you need. No problems with trust settings either.
Are you sure this is correct?
feedXML="\customxml.xml";
Perhaps, what you want is:
feedXML="\\customxml.xml"; //escape the back-slash.
or
feedXML="/customxml.xml"; // use the forward-slash.
Anyway, if you just want to wrap your user control inside a Web part, you don't need the SmartPart. You can write your custom Web part yourself quite easily.