I have a problem in a SharePoint list - some fields appear twice on the Display form, New Item form and on the list settings page. Both fields have the same ID and the same property page (same URL), so hiding one hides the other.
Using SharePoint Manager I can only see one field, but maybe I looked at the wrong places?
Has anyone experienced something similar, and how can I solve this issue?
i got the same issue,after adding column in list definition, they starts appearing twice in new/edit/view item forms. I just changed the column ordering in list settings and the problem was solved.
Yepp, I´ve had those problems working with contenttypes added to lists. When I´ve made updates on the contenttypes somehow the I have sometimes gotten duplicates. When I have looked at them they seem to be the same Ids and Names but the id is actually different.
The solution that I´ve used (works with contenttypes at least) is to compare the fieldlinks on the site contenttypes with the fieldlinks in the actual xml file (feature) that contains the contenttype. If they are not the same number of fieldlinks...take actions to remove the duplicates.
It is not wise to update the xml that creates the content type. If you want to add fields later on to the content type, do it through a new feature, see this link.
MSDN Article
Note the following text
Under no circumstances should you update the content type definition file for a content type after you have installed and activated that content type. Windows SharePoint Services does not track changes made to the content type definition file. Therefore, you have no method for pushing down changes made to site content types to the child content types.
For information about best practices when making changes to content types that have been installed and activated, see Updating Content Types.
Use this powershell script to clean dublicates:
Clear-Host
Add-PSSnapin microsoft.sharepoint.powershell -ErrorAction SilentlyContinue
[System.Reflection.Assembly]::Load("Microsoft.SharePoint, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c")
$web=Get-SPWeb "http://weburl.here"
function cleanFieldLinks($listName){
$list = $web.GetList($listName)
$ct = $list.ContentTypes[0];
$flDub = $ct.FieldLinks | group-object DisplayName | where { $_.Count -gt 1 }
foreach($fl in $flDub) {
$skipFirst = $fl.Group | select-object -skip 1
foreach($flDel in $skipFirst){
$ct.FieldLinks.Delete($flDel.Id)
}
}
$ct.Update()
}
cleanFieldLinks("lists/listurl")
$web.Dispose()
1) First, I wanted to mention that I came across this issue as I was working towards making my MOSS 2007 solution package compatible with MOSS 2013. MOSS 2013 does not seem to like duplicate field names. So if you have custom fields that have the same name as a field that comes with MOSS 2013, you will get a duplicate field name was found error.
2) This forced me to have to go back and update my custom fields and content types. I came across the issue where my field names were appearing multiple times after making the changes to the custom fields that were causing the duplicate field name issue.
3) I wrote a web forms page to resolve the issue of having the field show up multiple times on your view, new, and edit forms. You just will have to modify the code to specify the list you want to check. This version will delete the first instance of the fieldref and keep the second instance:
using System;
using System.Collections;
using System.Configuration;
using System.Data;
//using System.Linq;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.HtmlControls;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
//using System.Xml.Linq;
using Microsoft.SharePoint;
using System.Text;
using System.Collections.Generic;
public partial class FixDuplicateFieldIssue : Microsoft.SharePoint.WebControls.LayoutsPageBase
{
protected void Page_Load(object sender, EventArgs e)
{
if (SPContext.Current.Web.CurrentUser == null)
{
Response.Write("You must be logged in to view this page.");
Response.End();
return;
}
if (!SPContext.Current.Web.DoesUserHavePermissions(SPBasePermissions.ManageWeb))
{
Response.Write("You do not have permissions to view this page.");
Response.End();
return;
}
lblOutput.Text = "";
StringBuilder sbOutput = new StringBuilder();
using (SPSite site = new SPSite(SPContext.Current.Site.ID))
{
using (SPWeb web = site.OpenWeb(SPContext.Current.Web.ID))
{
try
{
hlBack.NavigateUrl = web.Url;
//open the List **** SPECIFY THE LISTNAME HERE ***
SPList spList = web.Lists["LISTNAME"];
if (spList != null)
{
//Check FieldLinks
sbOutput.Append("<table border='1'>");
foreach (SPContentType ct in spList.ContentTypes)
{
sbOutput.Append("<tr>");
sbOutput.Append("<td>" + ct.Name + "</td>");
sbOutput.Append("<td>");
Dictionary<string, Guid> GuidDictionary = new Dictionary<String, Guid>();
List<Guid> RepeatList = new List<Guid>();
//SEARCH THE CONTENT TYPE FOR REPEAT SPFieldLinks
foreach (SPFieldLink spfl in ct.FieldLinks)
{
if (!GuidDictionary.ContainsKey(spfl.Name.ToLower()))
{
GuidDictionary.Add(spfl.Name.ToLower(), spfl.Id);
}
else if (GuidDictionary[spfl.Name.ToLower()].ToString().ToLower()!=spfl.Id.ToString().ToLower())
{
//Record the GUID of the repeat SPFieldLink you want to delete in the RepeatList. In this case, we're recording the first item. If you want to delete the second one, add the spfl.Id instead.
RepeatList.Add(GuidDictionary[spfl.Name.ToLower()]);
sbOutput.Append("<span style='color:red;'>*</span>");
}
sbOutput.Append(spfl.Name + "," + spfl.Id + "," + spfl.DisplayName +"<br />");
}
sbOutput.Append("</td>");
sbOutput.Append("<td>");
sbOutput.Append("Repeats found: " + RepeatList.Count + "<br />");
//DELETE THE Repeat Field Links
foreach (Guid idToDelete in RepeatList)
{
sbOutput.Append("Deleting FieldRef with ID= " + idToDelete.ToString() + "<br />");
web.AllowUnsafeUpdates = true;
ct.FieldLinks.Delete(idToDelete);
ct.Update();
web.AllowUnsafeUpdates = false;
}
sbOutput.Append("</td>");
sbOutput.Append("</tr>");
}
sbOutput.Append("</table>");
}
}
catch (Exception ex)
{
sbOutput.Append("Error Occurred: " + ex.ToString());
}
}
}
lblOutput.Text = sbOutput.ToString();
}
}
Related
Can anyone help me ,I want to customize upload functionality in which i want to validate the uploaded image type to the picture library
where can i set my script ?? Any one can advise ???
You might be Use ItemAdding. In ItemAdding Event Method just check extension of the Document before successfully uploaded to the Library.if unvalid document than through Error message
your code something like this :
protected string[] ValidExtensions = new string[] { "png", "jpeg", "gif"};
public override void ItemAdding(SPItemEventProperties properties)
{
string strFileExtension = Path.GetExtension(properties.AfterUrl);
bool isValidExtension = false;
string strValidFileTypes = string.Empty;
using (SPWeb web = properties.OpenWeb())
{
foreach (string strValidExt in ValidExtensions)
{
if (strFileExtension.ToLower().EndsWith(strValidExt.ToLower()))
{
isValidExtension = true;
}
strValidFileTypes += (string.IsNullOrEmpty(strValidFileTypes) ? "" : ", ") + strValidExt;
}
// Here i am going to check is this validate or not if not than redirect to the
//Error Message Page.
if (!isValidExtension)
{
properties.Status = SPEventReceiverStatus.CancelWithRedirectUrl;
properties.RedirectUrl = properties.WebUrl + "/_layouts/error.aspx?ErrorText=" + "Only " + strValidFileTypes + " extenstions are allowed";
}
}
}
You could use SPItemEventReceiver for your library and add your logic into ItemUpdating() and ItemAdding() methods.
You can try creating a custom list template and replace the default NewForm.aspx and EditForm.aspx pages there. These custom form templates need not contain the same user controls and buttons as in the default picture library template. You could create a Silverlight web part with rich UI to upload images, e.g. The more you want to differ the more code you'll have to write...
An OOTB solution I can think of would be a workflow that you would force every new picture to run through but it would be quite an overkill for the end-user...
Of course, if you're able to validate by using just the meta-data in ItemAdding as the others suggest, it'd be a huge time-saver.
--- Ferda
From code I've automatically created a lot of similar sites (SPWeb) in my site collection from a site template (in Sharepoint Foundation). Every site has a home page on which I've added the "what's new" web part (found under "Social collaboration").
Even though the web part has several "target lists" (I'd have called it "source lists") added to it on the template site, this connection is lost on the sites created from the template. So I need to programmatically find all these web parts and add the target lists to them. Looping the web parts is not an issue - I've done that before - but I can't seem to find a word on the net on how to go about modifying this particular web part. All I have is a brief intellisense.
I've found out that it recides in the
Microsoft.SharePoint.Applications.GroupBoard.WebPartPages
namespace, but on the lists provided on MSDN this is one of very few namespaces that doesn't have a link to a reference documentation.
Does anyone have any experience of modifying this web part from code? If not, how would you go about to find out? I can't seem to figure out a method for this..
Here is how I did it. It worked really well. I had a feature that created several list instances and provisioned the What's New web part. In the Feature Receiver, I looped through all of the list instances, indexed the Modified field, and then added the list to the web part:
private void ConfigureLists(SPWeb web, SPFeatureReceiverProperties properties)
{
List<Guid> ids = new List<Guid>();
SPElementDefinitionCollection elements =
properties.Feature.Definition.GetElementDefinitions(new CultureInfo((int)web.Language, false));
foreach (SPElementDefinition element in elements)
{
if ("ListInstance" == element.ElementType)
{
XmlNode node = element.XmlDefinition;
SPList list = web.Lists[node.Attributes["Title"].Value];
SPField field = list.Fields[SPBuiltInFieldId.Modified];
if (!field.Indexed)
{
field.Indexed = true;
field.Update();
}
ids.Add(list.ID);
}
}
string targetConfig = string.Empty;
foreach (Guid id in ids)
{
targetConfig += string.Format("'{0}',''\n", id);
}
SPFile file = web.GetFile("Pages/default.aspx");
file.CheckOut();
using (SPLimitedWebPartManager manager = file.GetLimitedWebPartManager(PersonalizationScope.Shared))
{
WhatsNewWebPart webpart = null;
foreach (System.Web.UI.WebControls.WebParts.WebPart eachWebPart in manager.WebParts)
{
webpart = eachWebPart as WhatsNewWebPart;
if (null != webpart)
{
break;
}
}
if (null != webpart)
{
webpart.TargetConfig = targetConfig;
manager.SaveChanges(webpart);
}
}
file.CheckIn("ConfigureWebParts");
file.Publish("ConfigureWebParts");
file.Approve("ConfigureWebParts");
}
If you are unsure about the property, export the web part from the browser, then open the .webpart/.dwp file with a text editor. Somewhere in the xml will be a reference to the source list.
*.webparts are usually easier to modify, just set the property.
*.dwps are harder because you sometimes have to get the property (eg ViewXML), then load it into an XmlDocument, then replace the property, and write the xml document string value back to ViewXML.
Where can I find a log of login attempts to share point 2007?
Thanks.
PS: I have another question too, I 'd be really grateful if anybody helps me on it:
Sharepoint users are logged out
I haven't been able to find much without a third party tool. Our group is looking into acquiring DocAve by AvePoint.
In the mean time you can at least get an idea in your site analytics area of your site settings dashboard to see how many people have encountered the /_layouts/accessdenied.aspx page. It wont tell you much, but perhaps you can find a way to customize and add a snippet of code that will take a user's ID when they hit that page. Its not perfect, so I'd suggest a 3rd party tool unless you can scan all of your web front ends etc.
We had a similar requirement once, where we needed to log the last visited time of all the users on the site. So after some period of time, say 90 days, if a particular user had not logged into the site, the admin could delete his profile.
We overcame this problem with a very simple approach. You can follow the sample code for your reference.
You would need to create a list in your site by the name "UserLoginDetails" and create a column "LastLogIn" in that. Code is self explanatory.
using System;
using System.ComponentModel;
using System.Runtime.InteropServices;
using System.Web.UI;
using System.Xml.Serialization;
using Microsoft.SharePoint;
namespace Ubaid.WebParts
{
[Guid("883a77d6-271d-4b88-9ca2-d5150a00520b")]
[DefaultProperty("Text"), ToolboxData("<{0}:UserLastVisited runat=server></{0}:UserLastVisited>"), XmlRoot(Namespace = "Ubaid.WebParts")]
public class UserLastVisited : System.Web.UI.WebControls.WebParts.WebPart
{
protected override void CreateChildControls()
{
base.CreateChildControls();
string siteName = SPContext.Current.Web.Url;
using (SPSite site = new SPSite(siteName))
{
SPWeb web = site.OpenWeb();
site.AllowUnsafeUpdates = true;
web.AllowUnsafeUpdates = true;
SPList UserLoginDetailsList = web.Lists["UserLoginDetails"];
SPQuery query = new SPQuery();
string uname = SPContext.Current.Web.CurrentUser.LoginName;
query.Query = "<Where><Eq><FieldRef Name='Title'/><Value Type='Text'>" + uname + "</Value></Eq></Where>";
SPListItemCollection listItemColl = UserLoginDetailsList.GetItems(query);
if (listItemColl.Count > 0)
{
SPListItem item = listItemColl[0];
item["LastLogIn"] = DateTime.Now.ToLocalTime();
item.Update();
}
else
{
SPListItem item = UserLoginDetailsList.Items.Add();
item["Title"] = uname;
item["LastLogIn"] = DateTime.Now.ToLocalTime();
item.Update();
}
}
}
}
}
You can insert this webpart in your masterpage, as the data in this list needs to be updated on every page load.
Not sure which is the best way to do it / performance issues, but since ours was a small site we could manage with this pretty well.
I'm logged in as the System Account, so it's probably not a "real access denied"!
What I've done :
- A custom master page
- A custom page layout from a custom content type (with custom fields)
If I add a custom field (aka "content field" in the tools in SPD) in my page layout, I get an access denied when I try to edit a page that comes from that page layout.
So, for example, if I add in my page layout this line in a "asp:content" tag :
I get an access denied. If I remove it, everyting is fine. (the field "test" is a field that comes from the content type).
Any idea?
UPDATE
Well, I tried in a blank site and it worked fine, so there must be something wrong with my web application :(
UPDATE #2
Looks like this line in the master page gives me the access denied :
<SharePoint:DelegateControl runat="server" ControlId="PublishingConsole" Visible="false"
PrefixHtml="<tr><td colspan="0" id="mpdmconsole" class="s2i-consolemptablerow">"
SuffixHtml="</td></tr>"></SharePoint:DelegateControl>
UPDATE #3
I Found http://odole.wordpress.com/2009/01/30/access-denied-error-message-while-editing-properties-of-any-document-in-a-moss-document-library/
Looks like a similar issue. But our Sharepoint versions are with the latest updates. I'll try to use the code that's supposed to fix the lists and post another update.
** UPDATE #4**
OK... I tried the code that I found on the page above (see link) and it seems to fix the thing. I haven't tested the solution at 100% but so far, so good. Here's the code I made for a feature receiver (I used the code posted from the link above) :
using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.SharePoint;
using System.Xml;
namespace MyWebsite.FixAccessDenied
{
class FixAccessDenied : SPFeatureReceiver
{
public override void FeatureActivated(SPFeatureReceiverProperties properties)
{
FixWebField(SPContext.Current.Web);
}
public override void FeatureDeactivating(SPFeatureReceiverProperties properties)
{
//throw new Exception("The method or operation is not implemented.");
}
public override void FeatureInstalled(SPFeatureReceiverProperties properties)
{
//throw new Exception("The method or operation is not implemented.");
}
public override void FeatureUninstalling(SPFeatureReceiverProperties properties)
{
//throw new Exception("The method or operation is not implemented.");
}
static void FixWebField(SPWeb currentWeb)
{
string RenderXMLPattenAttribute = "RenderXMLUsingPattern";
SPSite site = new SPSite(currentWeb.Url);
SPWeb web = site.OpenWeb();
web.AllowUnsafeUpdates = true;
web.Update();
SPField f = web.Fields.GetFieldByInternalName("PermMask");
string s = f.SchemaXml;
Console.WriteLine("schemaXml before: " + s);
XmlDocument xd = new XmlDocument();
xd.LoadXml(s);
XmlElement xe = xd.DocumentElement;
if (xe.Attributes[RenderXMLPattenAttribute] == null)
{
XmlAttribute attr = xd.CreateAttribute(RenderXMLPattenAttribute);
attr.Value = "TRUE";
xe.Attributes.Append(attr);
}
string strXml = xe.OuterXml;
Console.WriteLine("schemaXml after: " + strXml);
f.SchemaXml = strXml;
foreach (SPWeb sites in site.AllWebs)
{
FixField(sites.Url);
}
}
static void FixField(string weburl)
{
string RenderXMLPattenAttribute = "RenderXMLUsingPattern";
SPSite site = new SPSite(weburl);
SPWeb web = site.OpenWeb();
web.AllowUnsafeUpdates = true;
web.Update();
System.Collections.Generic.IList<Guid> guidArrayList = new System.Collections.Generic.List<Guid>();
foreach (SPList list in web.Lists)
{
guidArrayList.Add(list.ID);
}
foreach (Guid guid in guidArrayList)
{
SPList list = web.Lists[guid];
SPField f = list.Fields.GetFieldByInternalName("PermMask");
string s = f.SchemaXml;
Console.WriteLine("schemaXml before: " + s);
XmlDocument xd = new XmlDocument();
xd.LoadXml(s);
XmlElement xe = xd.DocumentElement;
if (xe.Attributes[RenderXMLPattenAttribute] == null)
{
XmlAttribute attr = xd.CreateAttribute(RenderXMLPattenAttribute);
attr.Value = "TRUE";
xe.Attributes.Append(attr);
}
string strXml = xe.OuterXml;
Console.WriteLine("schemaXml after: " + strXml);
f.SchemaXml = strXml;
}
}
}
}
Just put that code as a Feature Receiver, and activate it at the root site, it should loop trough all the subsites and fix the lists.
SUMMARY
You get an ACCESS DENIED when editing a PAGE or an ITEM
You still get the error even if you're logged in as the Super Admin of the f****in world (sorry, I spent 3 days on that bug)
For me, it happened after an import from another site definition (a cmp file)
Actually, it's supposed to be a known bug and it's supposed to be fixed since February 2009, but it looks like it's not.
The code I posted above should fix the thing.
Try to publish your MasterPage and Page Layouts, this is the most common reason. Since the system account is godmode, it wont get that error.
In SharePoint Designer you cannot do the last step in the publishing workflow (Approval), so you:
SharePoint Designer:
CheckIn => Publish Major Version, hit the OK button or go to /_catalogs/masterpage on the site .
Then and use the Context Menu to Approve the MasterPage and Layouts.
Some ideas:
Check if any web parts in your custom Page Layout and Master Page are not registered as safe.
Did you define your own custom field type, like write a class which extends SPField? If so, are you using a custom Field Control? If you are, check if it is doing anything which may need elevated privileges.
Likewise, check for any edit mode panels containing web parts of web controls which might be trying to do something which needs elevated privileges.
See the code I've posted in the edit of the post. It fixed my problem.
The problem appears to be caused by an error in the stsadm -o export function in certain versions of SharePoint (I got it doing an export from a 2007 RTM MOSS server). Importing the bogus export file causes the "edit-denied-access" problem in all NEWLY-CREATED lists. The patches for later version from Microsoft fix stsadm -o export, but DO NOT FIX the broken lists; that requires a procedure like tinky05's.
Edit: This is a decade old so very likely not to be relevant to anyone, if google has brought you here I would be sceptical of the content against more modern frameworks!
We have a sharepoint website that has been quite heavily developed with content using the out of the box content editor webpart. This is a bit rubbish when it comes to using any other browser than IE.
We have in mind to update to the free Telerik content editor, however we would like to save ourselves a large amount of copy and pasting, and clicking and selecting to swap the web parts over.
There seems to be no official upgrade path but it seems to me that it must be possible to use the power of code (tm) to grab the content of the original webpart, new up a telerik webopart and put the content into the new webpart... then delete the old original web part.
Has anyone done this sort of thing? How is it best to lay out the code and actually run the code that will do the swap (if it is possible). A fresh webpart with a "Do Swap" button on? or something more sophisticated?
I also would need to walk through every page and subsite (and page in subsite) and look at every web part. Is there a best practice way of doing this?
I would write a console application for this.
Open the root Web and iterate through its sub webs.
Do the work needed for each page, by opening the WebPartManager.
Here are some pseudo code to get you started.
string SourceUrl = "http://ThisWeb";
using (SPSite sourceSite = new SPSite(SourceURL))
{
using (SPWeb sourceWeb = sourceSite.OpenWeb(SourceURL))
{
IterateSubWebsProd(sourceWeb):
}
}
private void IterateSubWebsProd(SPWeb sourceWeb)
{
// This is the migration function
DoThingyWithThisWeb(sourceWeb);
foreach (SPWeb subWeb in sourceWeb.Webs)
{
IterateSubWebsProd(subWeb);
subWeb.Dispose();
}
}
private void DoThingyWithThisWeb(SPWeb sourceWeb)
{
PublishingPage currentPage = null;
string currentPageName = "<something>";
// Find the pages that you want to modify, with a CAML query for example
SPQuery query = new SPQuery();
query.Query = string.Format("" +
"<Where>" +
"<Eq>" +
"<FieldRef Name='FileLeafRef' />" +
"<Value Type='File'>{0}</Value>" +
"</Eq>" +
"</Where>" +
"", currentPageName);
// This codesnippet is from a Publishing web example
PublishingWeb publishingWeb = PublishingWeb.GetPublishingWeb(sourceWeb);
PublishingPageCollection pageColl = publishingWeb.GetPublishingPages(query);
if (pageColl.Count > 0)
{
currentPage = pageColl[0];
}
using (SPLimitedWebPartManager wpMan = currentPage.ListItem.File.GetLimitedWebPartManager(System.Web.UI.WebControls.WebParts.PersonalizationScope.Shared))
{
foreach (WebPart wp in wpMan.WebParts)
{
if (wp.GetType().Equals(typeof(Microsoft.SharePoint.WebPartPages.ContentEditorWebPart)))
{
Microsoft.SharePoint.WebPartPages.ContentEditorWebPart thisWebPart = wp as Microsoft.SharePoint.WebPartPages.ContentEditorWebPart;
// This is just dummy code, here you will do your content migration
XmlDocument xmlDoc = new XmlDocument();
XmlElement xmlElement = xmlDoc.CreateElement("RootElement");
xmlElement.InnerText = sourceItem[SourceField].ToString();
thisWebPart.Content = xmlElement;
wpMan.SaveChanges(thisWebPart);
}
}
}
}
I'm not 100% certain on this, but if your content is saved into a list as individual fields, could you not point the Telerik controls at where that content is saved? This may cause Telerik controls to freak out a bit on the first edit of that content, but they should be ok to re-format the content and recover.