How to get the Absolute URL of a file in sharepoint library - sharepoint

I am working on SharePoint 2010.I have an documentlibrary ID and document ID in that library with me.i don't have either web,site in which the document library is present.So now I have to get the Full URL of the document at runtime.How can I get it .
I have tried the following.
string filepath = currentList.DefaultViewUrl + "/" + sListItem.Url;
Please answer this.

Use the field "EncodedAbsUrl" on the SPListItem. Works for SPFile as well:
SPListItem item = ...;
string absUrl = (string) item[SPBuiltInFieldId.EncodedAbsUrl];
or for a SPFile
SPFile file = ...;
string absUrl = (string) file.Item[SPBuiltInFieldId.EncodedAbsUrl];

The built in field id is for sure the best way to go but it returns the Url as encoded which may or may not be what you want.
I think the best way is to add a little extension method to a utilities class somewhere:
public static string AbsoluteUrl(this SPFile File, bool Decode = true)
{
string EncodedUrl = File.Item[SPBuiltInFieldId.EncodedAbsUrl].ToString();
if (Decode)
return SPEncode.UrlDecodeAsUrl(EncodedUrl);
else
return EncodedUrl;
}
And then call as follows
Item.File.AbsoluteUrl();
if you want a decoded Url or
Item.File.AbsoluteUrl(false);
if you want the Url to remain encoded.
Note that the default parameter value for Decode will only be available in .Net4+ and therefore SP2013 only but you can easily create an overload method for SP2010. You'll also need a reference to Microsoft.SharePoint.Utilities namespace to access the SPEncode class.

Try this ,
using (SPSite ospSite = new SPSite("http://abcd:24931"))
{
using (SPWeb web = ospSite.OpenWeb("/subsite")
{
// Get document library collection here and fetch all the document urls
SPDocumentLibrary docLib = (SPDocumentLibrary)web.Lists["docu"];
//where docu is my document library
SPListItemCollection items = docLib.Items;
foreach (SPListItem item in items)
{
string url = item.Url;
}
}
}
Hope this shall get you going.

public string GetItemURL(SPListItem item)
{
string web = item.Web.Url;
string listID = item.ParentList.ID.ToString();
string contentType = item.ContentTypeId.ToString();
string itemID = item.ID.ToString();
string url = web+"/_layouts/listform.aspx?PageType=4&ListID={"+listID+"}&ID="+itemID+"&ContentTypeID="+contentType;
return url;
}
It's Working for me. Hope I help (List Item url)

If this is for the document library, try this one.
item.Web.Url+"/"+item.File.Url

Use below code to get absolute URL of file:
SPFile file;
string url = file.Item[SPBuiltInFieldId.EncodedAbsUrl] as string;

For what it's worth, accessing the item.Web property means you are actually instantiating the SPWeb object which means that this should be disposed otherwise you'll be causing memory leakage.
It's a lot of overhead when there are better and quicker ways already mentioned.
I would use the BuiltInFieldId.EncodedAbsUrl approach mentioned since this gives you the easiest access to what you want.

The answer is
string url = currentweb.url+"/"+ Listitem.url;

Related

Customizing upload file functionality in SharePoint picture library

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

How to programmatically add target lists to the what's new web part in Sharepoint (or how to handle undocumented namespaces)

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.

Programmatically Edit Infopath Form Fields?

I have a form library in my share point site. Programmatically I need to fill some fields. Can I do that? If any one know please provide me some sample code. First I need to retrieve the infopath document and then I need to fill the fields.
What axel_c posted is pretty dang close. Here's some cleaned up and verified working code...
public static void ChangeFields()
{
//Open SharePoint site
using (SPSite site = new SPSite("http://<SharePoint_Site_URL>"))
{
using (SPWeb web = site.OpenWeb())
{
//Get handle for forms library
SPList formsLib = web.Lists["FormsLib"];
if (formsLib != null)
{
foreach (SPListItem item in formsLib.Items)
{
XmlDocument xml = new XmlDocument();
//Open XML file and load it into XML document
using (Stream s = item.File.OpenBinaryStream())
{
xml.Load(s);
}
//Do your stuff with xml here. This is just an example of setting a boolean field to false.
XmlNodeList nodes = xml.GetElementsByTagName("my:SomeBooleanField");
foreach (XmlNode node in nodes)
{
node.InnerText = "0";
}
//Get binary data for new XML
byte[] xmlData = System.Text.Encoding.UTF8.GetBytes(xml.OuterXml);
using (MemoryStream ms = new MemoryStream(xmlData))
{
//Write data to SharePoint XML file
item.File.SaveBinary(ms);
}
}
}
}
}
}
The Infopath document is just a regular XML file, the structure of which matches the data sources you defined in the Infopath form.
You just need to access the file via the SharePoint object model, modify it using standard methods (XmlDocument API) and then write it back to the SharePoint list. You must be careful to preserve the structure and insert valid data or you won't be able to open the form using Infopath.
You should really check out a book on SharePoint if you plan to do any serious development. Infopath is also a minefield.
Object model usage examples: here, here and here. The ridiculously incomplete MSDN reference documentation is here.
EDIT: here is some example code. I haven't done SharePoint for a while so I'm not sure this is 100% correct, but it should give you enough to get started:
// Open SharePoint site
using (SPSite site = new SPSite("http://<SharePoint_Site_URL>"))
{
using (SPWeb web = site.OpenWeb())
{
// Get handle for forms library
SPList formsLib = web.Lists["FormsLib"];
if (formsLib != null)
{
SPListItem itm = formsLib.Items["myform.xml"];
// Open xml and load it into XML document
using (Stream s = itm.File.OpenBinary ())
{
MemoryStream ms;
byte[] xmlData;
XmlDocument xml = new XmlDocument ();
xml.Load (s);
s.Close ();
// Do your stuff with xml here ...
// Get binary data for new XML
xmlData = System.Text.Encoding.UTF8.GetBytes (xml.DocumentElement.OuterXml);
ms = new MemoryStream (xmlData);
// Write data to sharepoint item
itm.File.SaveBinary (ms);
ms.Close ();
itm.Update ();
}
}
web.Close();
}
site.Close();
}
It depends a bit on your available tool set, skills and exact requirements.
There are 2 main ways of pre populating data inside an InfoPath form.
Export the relevant fields as part of the form's publishing process. The fields will then become columns on the Document / Forms library from where you can manipulate them either manually, via a Workflow or wherever your custom code is located.
Directly manipulate the form using code similar to what was provided by Axel_c previously. The big question here is: what will trigger this code? An event receiver on the Document Library, a SharePoint Designer Workflow, a Visual Studio workflow etc?
If you are trying to do this from a SharePoint Designer workflow then have a look at the Workflow Power Pack for SharePoint. It allows C# and VB code to be embedded directly into the workflow without the need for complex Visual Studio development. An example of how to query InfoPath data from a workflow can be found here. If you have some development skills you should be able to amend it to suit your needs.
I also recommend the site www.infopathdev.com, they have excellent and active forums. You will almost certainly find an answer to your question there.
Thanks for the sample code, #axel_c and #Jeff Burt
Below is just the same code from Jeff Burt modified for a file in Document set which I needed. If you don't already have the Document Set reference, you can check out this site on how to grab one:
http://howtosharepoint.blogspot.com/2010/12/programmatically-create-document-set.html
Also, the codes will open the .xml version of the infopath form and not the .xsn template version which you might run into.
Thanks again everyone...
private void ChangeFields(DocumentSet docSet)
{
string extension = "";
SPFolder documentsetFolder = docSet.Folder;
foreach (SPFile file in documentsetFolder.Files)
{
extension = Path.GetExtension(file.Name);
if (extension != ".xml") //check if it's a valid xml file
return;
XmlDocument xml = new XmlDocument();
//Open XML file and load it into XML document, needs to be .xml file not .xsn
using (Stream s = file.OpenBinaryStream())
{
xml.Load(s);
}
//Do your stuff with xml here. This is just an example of setting a boolean field to false.
XmlNodeList nodes = xml.GetElementsByTagName("my:fieldtagname");
foreach (XmlNode node in nodes)
{
node.InnerText = "xyz";
}
//Get binary data for new XML
byte[] xmlData = System.Text.Encoding.UTF8.GetBytes(xml.OuterXml);
using (MemoryStream ms = new MemoryStream(xmlData))
{
//Write data to SharePoint XML file
file.SaveBinary(ms);
}
}
}
I had this issue and resolved it with help from Jeff Burt / Axel_c's posts.
I was trying to use the XMLDocument.Save([stream]) and SPItem.File.SaveBinary([stream]) methods to write an updated InfoPath XML file back to a SharePoint library. It appears that XMLDocument.Save([stream]) writes the file back to SharePoint with the wrong encoding, regardless of what it says in the XML declaration.
When trying to open the updated InfoPath form I kept getting the error "a calculation in the form has not been completed..."
I've written these two functions to get and update and InfoPath form. Just manipulate the XML returned from ReadSPFiletoXMLdocument() in the usual way and send it back to your server using WriteXMLtoSPFile().
private System.Xml.XmlDocument ReadSPFiletoXMLdocument(SPListItem item)
{
//get SharePoint file XML
System.Xml.XmlDocument xDoc = new System.Xml.XmlDocument();
try
{
using (System.IO.Stream xmlStream = item.File.OpenBinaryStream())
{
xDoc.Load(xmlStream);
}
}
catch (Exception ex)
{
//put your own error handling here
}
return xDoc;
}
private void WriteXMLtoSPFile(SPListItem item, XmlDocument xDoc)
{
byte[] xmlData = System.Text.Encoding.UTF8.GetBytes(xDoc.OuterXml);
try
{
using (System.IO.MemoryStream outStream = new System.IO.MemoryStream(xmlData))
{
item.File.SaveBinary(outStream);
}
}
catch (Exception ex)
{
//put your own error handling here
}
}

How to create a wiki page (=item) in Sharepoint programmatically?

how do I create a wiki page and add a title, as well as some content in sharepoint (via webservices)?
This is my SOAP message so far:
<soapenv:Body>
<soap:UpdateListItems>
<soap:listName>Cooking Wiki</soap:listName>
<soap:updates>
<Batch OnError="Continue">
<Method ID="1" Cmd="New">
<Field Name="WikiField">Mix two eggs and a cup of milk.</Field>
</Method>
</Batch>
</soap:updates>
</soap:UpdateListItems>
</soapenv:Body>
It creates a new page, but it has no content and no title.
Grab a copy of SharePoint Manager it can show you heaps of interesting info.
you want the Name field (it includes the ".aspx").
The title field is not relevant in a wiki (blank), pages are indexed by thier name instead.
--update--
Using the copy.asmx allows you to upload a new document. The template page is a page that has been downloaded previously (it stores no information, equivalent to a layout page).
private byte[] GetTemplatePage()
{
FileStream fs = new FileStream("templatePage.aspx", FileMode.Open);
byte[] fileContents = new byte[(int)fs.Length];
fs.Read(fileContents, 0, (int)fs.Length);
fs.Close();
return fileContents;
}
private void UploadDoc(string pageName)
{
byte[] wikiBytes = GetTemplatePage();
string dest = "http://[website]/wiki/Wiki%20Pages/" + pageName + ".aspx";
string[] destinationUrlArray = new string[] { dest };
IntranetCopy.Copy copyService = new IntranetCopy.Copy();
copyService.UseDefaultCredentials = true;
copyService.Url = "http://[website]/wiki/_vti_bin/copy.asmx";
IntranetCopy.FieldInformation fieldInfo = new IntranetCopy.FieldInformation();
IntranetCopy.FieldInformation[] fields = { fieldInfo };
IntranetCopy.CopyResult[] resultsArray;
copyService.Timeout = 600000;
uint documentId = copyService.CopyIntoItems(dest, destinationUrlArray, fields, wikiBytes, out resultsArray);
}
Then you can call the lists.asmx to update the wikifield.
Note: I have not figure out how to rename a document once it has been uploaded using webservices.
If nothing else is working you should develop your own web service to provide this feature. The out-of-the-box options are notoriously limited in functionality but there is nothing stopping you from adding to them.
I would wrap Nat's solution into the web service code.

Programmatically insert a List as a webpart in a webpart page in WSS 3.0

I tried searching on the net to programmatically insert a List as a webpart in a webpart page but was not lucky enough.
Any thoughts or ideas how i could Programmatically insert a List as a webpart in a webpart page
Many Thanks!
First add these using statements.
using Microsoft.SharePoint;
using Microsoft.SharePoint.WebPartPages;
Then in your code
// First get the list
SPSite site = new SPSite("http://myserver");
SPWeb web = site.OpenWeb();
SPList list = web.Lists["MyCustomlist"];
// Create a webpart
ListViewWebPart wp = new ListViewWebPart();
wp.ZoneID = "Top"; // Replace this ith the correct zone on your page.
wp.ListName = list.ID.ToString("B").ToUpper();
wp.ViewGuid = list.DefaultView.ID.ToString("B").ToUpper();
// Get the web part collection
SPWebPartCollection coll =
web.GetWebPartCollection("default.aspx", // replace this with the correct page.
Storage.Shared);
// Add the web part
coll.Add(wp);
If you want to use a custom view, try playing with this:
SPView view = list.GetUncustomizedViewByBaseViewId(0);
wp.ListViewXml = view.HtmlSchemaXml;
Hope it helps,
W0ut
You need to perform two steps to add a web part to a page. First you have to create the list you want to show on the page. Therefore you can use the Add() method of the web site's list collection (SPListCollection).
To show the list on the web part page you have to add a ListViewWebPart to the web part page using the SPLimitedWebPartManager of the page.
To make this more re-usable as part of a feature receiver, you could pass in the splist and spview as part of a method:
static public void AddEventsListViewWebPart(PublishingPage page, string webPartZoneId, int zoneIndex, string webPartTitle, PartChromeType webPartChromeType, string listName, string viewname)
{
using (SPLimitedWebPartManager wpManager = page.ListItem.File.GetLimitedWebPartManager(PersonalizationScope.Shared))
{
SPWeb web = page.PublishingWeb.Web;
SPList myList = web.Lists.TryGetList(listName);
using (XsltListViewWebPart lvwp = new XsltListViewWebPart())
{
lvwp.ListName = myList.ID.ToString("B").ToUpperInvariant();
lvwp.Title = webPartTitle;
// Specify the view
SPView view = myList.Views[viewname];
lvwp.ViewGuid = view.ID.ToString("B").ToUpperInvariant();
lvwp.TitleUrl = view.Url;
lvwp.Toolbar = "None";
lvwp.ChromeType = webPartChromeType;
wpManager.AddWebPart(lvwp, webPartZoneId, zoneIndex);
}
}
}
And then call it during feature activation:
AddEventsListViewWebPart(welcomePage, "Right", 1, "Events", PartChromeType.TitleOnly, "Events", "Calendar");

Resources