how to update infopath form library item field programatically? - sharepoint

I was successfully able to update one of the fields (which was of type boolean) from infopath for library item using sharepoint object Model as if it was a list item.
But for another field which is of type text, the same code just gets executed but does not change the field value !!!!
I am using following code, which works for that boolean field but for another field of type string , not sure why it is not working. Any idea ?
SPSecurity.RunWithElevatedPrivileges(delegate()
{
SPWeb web;
SPSite site = new SPSite("http://sharepointsite");
web = site.OpenWeb();
SPList formLibList = web.Lists["FormLibraryName"];
SPQuery query = new SPQuery(); query.Query = "<Where><Eq><FieldRef Name='Title' /><Value Type='Text'>" + titleName + "</Value></Eq></Where>";
web.Site.WebApplication.FormDigestSettings.Enabled = false;
web.AllowUnsafeUpdates = true;
SPListItemCollection col = formLibList.GetItems(query);
if (col.Count > 0)
{
col[0]["CustomerName"] = "test customer name";
col[0].Update();
}
web.Site.WebApplication.FormDigestSettings.Enabled = true; web.AllowUnsafeUpdates = false;
});
Thanks,
Nikhil

I had to declare SPListItem and set it instead of directly modifying list item collection.

It's not an answer to your question (you already found the solution yourself), but you may want to put your SPSite and SPWeb objects in a using block. In your example code you are not disposing them, which results in a memory leak. The correct way would be like this:
SPSecurity.RunWithElevatedPrivileges(delegate()
{
using (SPSite site = new SPSite("http://sharepointsite"))
{
using (SPWeb web = site.OpenWeb())
{
// the rest of your code
}
}
});

Related

Custom Filter Web Part to filter/update ListView Web Part

Scenario : I need Refresh/Filter the Items/records displayed in List View Web Part on the same page based on selected filters. So I created Visual Web Part and tried to modify the View of List View Web Part Programmatically. So far i have reached till here :
string spListName = "Job";
protected void BtnSearchClick(object sender, EventArgs e)
{
try
{
SPWeb oWebsite = SPContext.Current.Web;
SPList oList = oWebsite.Lists[spListName];
XsltListViewWebPart xsltWP = null;
SPWebPartManager wpManager = WebPartManager.GetCurrentWebPartManager(Page) as SPWebPartManager;
//Code to Find List View Web Part on Page
foreach (System.Web.UI.WebControls.WebParts.WebPart wp in wpManager.WebParts)
{
if (wp.GetType().Name == "XsltListViewWebPart")
xsltWP = wp as XsltListViewWebPart;
}
oWebsite.AllowUnsafeUpdates = true;
StringBuilder strbPreQuery = new StringBuilder("<Where><Eq>");
StringBuilder strbPostQuery = new StringBuilder("</Value></Eq></Where>");
string strQueryKeyword = "<FieldRef Name='Customer' /><Value Type='Lookup'>";
SPQuery oQuery = new SPQuery();
oQuery.Query = strbPreQuery.ToString() + strQueryKeyword + txtCustomer.Text + strbPostQuery.ToString();
SPListItemCollection itemCol = oWebsite.Lists[spListName].GetItems(oQuery);
PropertyInfo pi = xsltWP.GetType().GetProperty("ContextView", BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance);
SPView view = (SPView)(pi.GetValue(xsltWP, null));
view.Query = oQuery.Query;
view.Update();
wpManager.SaveChanges(xsltWP);
xsltWP.DataBind();
oWebsite.AllowUnsafeUpdates = false;
}
catch (Exception ex)
{
Response.Write(ex);
}
}
The Above code works but now I am facing following problems :
The results updation requires page refresh so If I add following code, results are updated but filter values in visual web part is lost.
this.Context.Response.Redirect(this.Context.Request.Url.ToString());
Filtered applied by one user is also reflected to another user.
Can some please help in to address these two problems I have ? that is I want
To preserve the filter values and results to be modified at the same time
The filtering should be only for one user and not for all.
Any help in this regards will be appreciated.
Create a SPQuery that will hold the default value of the view.
then after passing the value,
Use this to revert back the default query of the view.
SPView _view;
protected void Page_Unload(object sender, EventArgs e)
{
//your code
SPView view = (SPView)(pi.GetValue(xsltWP, null));
view.Query = _view.Query;
view.Update();
}

SPListItem not added to SPList

I'm using the following code to add an item to a list on the top level of my application but it is not adding anything, does anyone know why? Is there anything missing?
It doesn't return me any error, just doesn't add the item and the list remains empty.
The code is in the FeatureActivated method of the feature where the list instance is being deployed.
using (SPWeb web = site.OpenWeb())
{
web.AllowUnsafeUpdates = true;
SPList icons = web.GetList(path)
SPSecurity.RunWithElevatedPrivileges(delegate()
{
SPListItem icon = icons.Items.Add();
icon[SPBuiltInFieldId.Title] = "title";
icon[new Guid("d3429cc9-adc4-439b-84a8-5679070f84cb")] = "class1";
icons.Update();
}
you have to call the Update() method of the icon object, not icons.
I found out there are 2 ways of successfully add an item to a list:
Like Andreas Scharf said:
SPListItem item = list.Items.Add();
item["Title"] = "some title";
item.Update();
Some other way using the AddItem() instead of the Add() from the items collection
SPListItem item = list.AddItem();
item["Title"] = "some title"; // Add item's field values
item.Update(); //also the item is updated, not the list

update DateTime field with webservice UpdateListItems

is it possible to set a DateTime filed to be null/empty when calling UpdateListItems?
I can set the field to a date value, but not set it to be empty.
Yes, it's possible.
I have tested with both a required and non-required datefield and setting the field to null works.
using (SPSite site = new SPSite("http://intranet"))
{
using (SPWeb web = site.OpenWeb("site"))
{
SPList list = web.Lists["MyCustomList"];
SPListItem item = list.Items.Add();
item["Title"] = "My Item";
item["UpdateDate"] = null;
item.Update();
list.Update();
}
}

Will using a SPListItemCollection returned from a function reopen the SPWeb?

After reading Stefan Gossner's post about disposing objects and this question about Cross method dispose patterns, I found that I was guilty of accidentally reopening some SPWebs. I know in Stefan Gossner's post he mentions you should dispose of an SPWeb after you are finished with any child object. However, the microsoft documentation mentions Caching the SPListItemCollection object. Is the following code correct? Would the returned SPListItemCollection reopen an SPWeb object? Is there any way to tell for sure?
// is this correct????
private SPListItemCollection GetListItems()
{
SPListItemCollection items = null;
try
{
using (SPSite site = new SPSite(GetListSiteUrl()))
{
using (SPWeb web = site.OpenWeb())
{
// retrieve the list
SPList list = web.Lists[_ListName];
// more code to create the query...
items = list.GetItems(query);
}
}
}
catch (Exception e)
{
// log error
}
return items;
}
Edit 09/09/09
I am mainly referring to this part of Stefan Grossner's post:
You should dispose a SPWeb or SPSite
object after the last access to a
child object of this object.
I believe what he is saying is that if I use the SPListItemCollection after I dispose of the SPWeb that I used to get it... the SPWeb will be reopened automatically.
I found out after asking Stefan directly that the SPListItemCollection can indeed reopen the SPWeb after you dispose of it. This means that my code posted above is INCORRECT and I would only be able to dispose of the SPWeb after I use the SPListItemCollection.
Update: It is better to convert to the SPListItemCollection to something else and return that instead.
private DataTable GetListItems()
{
DataTable table = null;
try
{
SPListItemCollection items = null;
using (SPSite site = new SPSite(GetListSiteUrl()))
{
using (SPWeb web = site.OpenWeb())
{
// retrieve the list
SPList list = web.Lists[_ListName];
// more code to create the query...
items = list.GetItems(query);
// convert to a regular DataTable
table = items.GetDataTable();
}
}
}
catch (Exception e)
{
// log error
}
return table;
}
As far as I know the answer is no, but I would have written the code something like
private void FetchItems(Action<SPListItemCollection> action)
{
using(...)
{
var items = list.GetItems(query);
action(items);
}
}
By doing this, to call this method you would need to send a method along (delegate) that the SPListItemCollection should be used for, an example:
FetchItems( items => ....) or FetchItems( DoStuffWithItems(SPListItemCollection) )
If you are talking about whether you need an SPWeb in the same scope when you get around to using the SPListItemCollection, I think the answer is no.
For example, I routinely do the following:
private IEnumerable<SPListItem> AllItems;
public void GetItems()
{
var results = SPContext.Current.Web.Lists[ListName].Items.Cast<SPListItem>();
this.AllItems = results;
}
and then I use AllItems all over the place, and it works fine.
Incase you are wondering, the cast is done so I can use Linq on the result set - much much faster than submitting a query to the list, especially if you are doing multiple subselects on the data.

Filter a SharePoint list by audience

Using the SharePoint SDK, I'm attempting to retrieve a list and display the contents in a composite control. The list is audience aware and I'd like to maintain that in my control. How can I go about getting this list, filtered by audience, using the SharePoint SDK? Here's some of the code I'm working with:
SPWeb currentWeb = SPContext.Current.Site.RootWeb;
SPList shortcuts = currentWeb.Lists["Shortcuts"];
Here's some of the code I'm using now, and it's not quite working for me. According to how the audiences are set up, I should be getting results:
protected override void CreateChildControls()
{
dropdown = new DropDownList();
dropdown.Items.Add(new ListItem("Select...", ""));
SPWeb currentWeb = SPContext.Current.Site.RootWeb;
SPList shortcuts = currentWeb.Lists["Shortcuts"];
ServerContext context = ServerContext.GetContext(currentWeb.Site);
AudienceManager audManager = new AudienceManager(context);
AudienceCollection audiences = audManager.Audiences;
AudienceLoader audienceLoader = AudienceLoader.GetAudienceLoader();
foreach (SPListItem listItem in shortcuts.Items)
{
string audienceFieldValue = (string)listItem["Target Audiences"];
if (AudienceManager.IsCurrentUserInAudienceOf(audienceLoader, audienceFieldValue, false))
{
dropdown.Items.Add(new ListItem(listItem.Title, listItem.Url));
}
}
Controls.Add(dropdown);
base.CreateChildControls();
}
On:
if (AudienceManager.IsCurrentUserInAudienceOf(audienceLoader, audienceFieldValue, false))
It's never returning true, even when it should be.
Here's a more succinct code snippet. Main changes are removal of unused objects, and a more efficient version of the foreach loop.
protected override void CreateChildControls()
{
dropdown = new DropDownList();
dropdown.Items.Add(new ListItem("Select...", ""));
SPWeb currentWeb = SPContext.Current.Site.RootWeb;
SPListItemCollection scItems = currentWeb.Lists["Shortcuts"].Items;
AudienceLoader audienceLoader = AudienceLoader.GetAudienceLoader();
// Iterate over a copy of the collection to prevent multiple queries to the list
foreach (SPListItem listItem in scItems)
{
string audienceFieldValue = (string)listItem["Target Audiences"];
if (AudienceManager.IsCurrentUserInAudienceOf(audienceLoader, audienceFieldValue, false))
{
dropdown.Items.Add(new ListItem(listItem.Title, listItem.Url));
}
}
Controls.Add(dropdown);
base.CreateChildControls();
}
Here's a code snippet that maybe could be of use, to determine each items audience:
SPList shortcuts = currentWeb.Lists["Shortcuts"];
SPListItemCollection items = list.Items;
Audience siteAudience;
ServerContext context = ServerContext.GetContext(site);
AudienceManager audManager = new AudienceManager(context);
foreach (SPListItem item in items)
{
string ID = item["Target Audiences"].ToString();
string NewID = ID.Remove(36);
Guid guid = new Guid(NewID);
siteAudience = audManager.GetAudience(guid);
}

Resources