Poor List Item Submit Logic in Sandbox Solution - c#

I have a web part for managing comments related to ongoing promotions. The web part is hosted in a Sandbox Solution because server access of all kinds is restricted (//sharepoint)
I have two main issues with my code.
1: Items submitted do not appear after postback, leaving user to think their comments was not saved,
2: PostBack data refires after page refresh, meaning if a user refreshes hoping to see their comments, it is re-submitted and saved.
What am I doing wrong here?
public string OfferID { get; set; }
protected void Page_Load(object sender, EventArgs e)
{
OfferID = Context.Request.QueryString["ItemID"];
LoadOffers();
}
protected void LoadOffers()
{
if (!String.IsNullOrEmpty(OfferID))
{
PopulateOfferDetails(OfferID);
PopulateComments(OfferID);
PopulateBestPractices(OfferID);
}
else
{
OfferID = "123";
PopulateOfferDetails(OfferID);
PopulateComments(OfferID);
PopulateBestPractices(OfferID);
}
}
protected void PopulateComments(string offerID)
{
rcOiD.InnerText += " " + offerID;
List<Comment> Comments = new List<Comment>();
SPList TargetList = web.Lists.TryGetList("Offer Comments");
SPQuery query = new SPQuery();
query.RowLimit = 100;
query.Query = "<Where><Eq><FieldRef Name=\"OfferID\"/><Value Type=\"Text\">" + offerID + "</Value></Eq></Where>";
try
{
SPListItemCollection items = TargetList.GetItems(query);
if (items.Count > 0)
{
commentsCount.InnerText = items.Count.ToString();
SPUser user = web.CurrentUser;
string alias = user.Email.Substring(0, user.Email.IndexOf('#'));
string profilePicBase = "<div class=\"profilePic\" " + "style=\"background-image:url('http://who/Photos/XX.jpg');\"" + "> </div>";
foreach (SPListItem item in items)
{
Comment c = new Comment();
c.Author = ((string)item["Created By"]).CleanUserName();
c.Body = (string)item["Body"];
c.Date = String.Format("{0:MMM dd, yyyy}", (DateTime)item["Created"]);
c.ProfilePic = profilePicBase.Replace("XX", alias);
Comments.Add(c);
}
Comments.Reverse();
CommentRepeater.DataSource = Comments;
CommentRepeater.DataBind();
}
else
{
commentsCount.InnerText = "0";
}
}
catch (Exception ex)
{
}
}
protected void SubmitListItem(object sender, EventArgs e)
{
if (Page.IsPostBack)
{
SPUser user = web.CurrentUser;
string alias = user.Email.Substring(0, user.Email.IndexOf('#'));
if (ListChoice.SelectedItem.Text == "comment")
{
SPList TargetList = web.Lists.TryGetList("Offer Comments");
SPListItem item = TargetList.Items.Add();
item["Title"] = TitleBox.Text;
item["Body"] = BodyBox.Text;
item["OfferID"] = OfferID;
item["Alias"] = alias;
item.SystemUpdate();
TargetList.Update();
}
else
{
SPList TargetList = web.Lists.TryGetList("Offer Best Practices");
SPListItem item = TargetList.Items.Add();
item["Title"] = TitleBox.Text;
item["Body"] = BodyBox.Text;
item["OfferID"] = OfferID;
item.SystemUpdate();
TargetList.Update();
}
}
}
EDIT: I can confirm this isn't a databind() issue. The item.count being pulled on postback is being rendered properly, but is still 1 item short.

I assume SubmitListItem is an event handler of an control on the page.
If that is so then as in your previous question, Page_Load is is fired before any control's event handler.
Therefore on postback your repeater is getting bound before the item addition occurs so on that load you do not get to see the new item.
To prevent this rebind the repeater after item addition.

I think you should do this only if not is page postback:
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
OfferID = Context.Request.QueryString["ItemID"];
LoadOffers();
}
}

Related

Avoid controls with same ID

I'm creating dynamically controls, assigning it at the same dynamically names and ID's but when I click over a button "A" and then over the button "B" and then again to the button "A" this throw me an error
Multiple controls with the same ID were found. FindControl requires that controls have unique IDs.
this is my code and how I try to avoid the repeating I
protected void DynamicButton()
{
//BAD TOOLS INTO THE LIST AND SHOW
List.ListUsers listsArea = new List.ListUsers();
List<Data.Area> Area = listsArea.AreaList();
List<Data.Area> ListOfEquiposNoOk = Area.Where(x => x.AREA == "ENG" && x.STANDBY == 1).ToList();
List<Button> BotonesBad = new List<Button>();
var TeamBad = ListOfEquiposNoOk.Select(x => x.TEAM).Distinct().ToList();
foreach (var team in TeamBad)
{
Button newButtonBad = new Button();
if (newButtonBad.ID != newButtonBad.ID)
{
BotonesBad = Bad.Controls.OfType<Button>().ToList();
BotonesBad.Add(newButtonBad);
}
else
{
newButtonBad.CommandName = "Btn" + Convert.ToString(team);
newButtonBad.ID = "BtnB_" + Convert.ToString(team);
newButtonBad.Text = team;
newButtonBad.CommandArgument = "ENG";
newButtonBad.Click += new EventHandler(newButton_Click);
Bad.Controls.Add(newButtonBad);
newButtonBad.Click += new EventHandler(newButton_Click);
newButtonBad.CssClass = "btn-primary outline separate";
}
}
I need the ID's to fire an UpdatePanel
ADDED
public partial class Dashboard : System.Web.UI.Page
{
static bool enableGood = false;
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
DynamicButton();
}
else if(enableGood)
{
DynamicButton();
}
}
protected void DButton(object sender, EventArgs e)
{
ScriptManager.RegisterStartupScript(this, this.GetType(), "Pop", "showAndHide();", true);
enableGood = true;
DynamicButton();
}
Assuming "team" is an object in this line:
newButtonBad.ID = "BtnB_" + Convert.ToString(team);
There could be your problem. ".ToString()" usually returns the type as string. So every button will get the same name (since they are all of type "team").
You could override ToString() in your team object, or use a specific team property (e.g team.ID). You could use the property like this:
newButtonBad.ID = "BtnB_" + team.ID.ToString();
Also as already pointed out in the comments, change your evaluation from
if (newButtonBad.ID != newButtonBad.ID)
to
if (team.ID != newButtonBad.ID)
That should do the trick.

'Find and Save' functionality not working

First time poster, long time lurker. I am having some trouble with my ASP.NET page, and I hope someone can help me resolve my issue.
Basically, I have a bunch of checkboxes in a gridview, and two buttons: a 'find' button, and a 'save' button. The 'find' can set the value of the checkbox, but if a user unchecks it, I want to capture that change when the user hits 'save'. Currently, it does not work.
Relevant ASPX:
<%# Page Language="C#" AutoEventWireup="true" EnableViewState="true" CodeBehind="FindTransactions.aspx.cs" Inherits="Basic.FindTransactions" MasterPageFile="~/Trans.Master" %>
Relevant Code Behind here:
Page:
public partial class FindTransactions : System.Web.UI.Page
{
GridView _gridview = new GridView() { ID = "_gridView" };
DataTable _datatable = new DataTable();
Int32 _buyerID = new Int32();
protected void Page_Load(object sender, EventArgs e)
{
}
"Find" button:
protected void Find_Click(object sender, EventArgs e)
{
//truncated
_datatable.Rows.Add(
//filled with other data from a custom object.
);
ViewState["_datatable"] = _datatable;
ViewState["_buyerID"] = _buyerID;
BuildGridView((DataTable)ViewState["_datatable"],(Int32)ViewState["buyerID"]);
}
BuildGridView function:
protected void BuildGridView(DataTable d, Int32 b)
{
_gridview.DataKeyNames = new String[] {"Transaction ID"};
_gridview.AutoGenerateColumns = false;
_gridview.RowDataBound += new GridViewRowEventHandler(OnRowDataBound);
for(Int32 i = 0; i < d.Columns.Count; i++)
{
Boundfield boundfield = new BoundField();
boundfield.DataField = d.Columns[i].ColumnName.ToString();
boundfield.HeaderText = d.Columns[i].ColumnName.ToString();
_gridview.Columns.Add(boundfield);
}
_gridview.DataSource = d;
_gridview.DataBind();
//truncated
Panel1.Controls.Add(_gridview);
}
Row Bound Event handler:
protected void OnRowDataBound(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.DataRow)
{
String controlID = "checkBox";
CheckBox c = new CheckBox() { ID = controlID};
c.Enabled = true;
Boolean success;
Boolean v;
success = Boolean.TryParse(e.Row.Cells[8].Text, out v);
e.Row.Cells[8].Controls.Add(c);
if (success)
{
c.Checked = v;
if (c.Checked)
{
//Will uncomment once other things work
//e.Row.Visible = false;
}
}
else
{
c.Checked = false;
}
}
}
All of that works. Here is where it starts to break down:
"Save" button:
protected void Save_Click(object sender, EventArgs e)
{
//Both for troubleshooting and both return 0. (Expected for datatable)
Label1.Text = _gridview.Rows.Count.ToString();
Label2.Text = _datatable.Rows.Count.ToString();
/*truncated
*/
if (grid.Rows.Count == 0)
{
BuildGridView((DataTable)ViewState["infoTable"], (Int32)ViewState["guestID"]);
}
foreach (GridViewRow r in grid.Rows)
{
if (r.RowType == DataControlRowType.DataRow)
{
CheckBox cb = (CheckBox)r.FindControl("checkBox");
if (cb != null && cb.Checked)
{
//This never seems to modify the label.
//Will put code to modify database here.
Label2.Text += "Hi " + r.RowIndex.ToString();
}
}
}
}
After I hit the save button, PostBack occurs and GridView is empty (Rows.Count is 0). ViewState appears to be lost before I get a chance to loop through the GridView rows to determine the checkbox values.
At the end of it all, I just want to capture the status of those checkboxes, changed by user interaction or not, by hitting the 'Save' button.
I found some other articles, but a lot of them haven't worked when I tried implementing the various fixes.
This one seems to be the closest that describes my issue, and the code is structured similarly, but I don't quite understand how to implement the fix: GridView doesn't remember state between postbacks
[New simplified code to illustrate problem:]
namespace GridViewIssue
{
public partial class GridViewNoMaster : System.Web.UI.Page
{
GridView _gridView = new GridView() { ID = "_gridView" };
DataTable _dataTable = new DataTable();
protected void Page_Load(object sender, EventArgs e)
{
}
protected void Find_Click(object sender, EventArgs e)
{
BuildDataTable();
List<String> list = new List<String>();
list.Add("1");
list.Add("User");
list.Add("10/12/2014");
foreach (String s in list)
{
_dataTable.Rows.Add(
list[0],
list[1],
list[2]
);
}
BuildGridView();
//Feedback.Text = _gridView.Rows.Count.ToString();
}
protected void Save_Click(object sender, EventArgs e)
{
Feedback.Text = "Save Clicked, PostBack: " + IsPostBack + ", GridView Row Count: " + _gridView.Rows.Count + ", GridView ViewState: " + _gridView.EnableViewState;
foreach (GridViewRow r in _gridView.Rows)
{
if(r.RowType == DataControlRowType.DataRow)
{
Feedback.Text = "In DataRow type" + _gridView.Rows.Count;
}
}
}
protected void BuildDataTable()
{
_dataTable.Columns.Add("Transaction ID", typeof(String));
_dataTable.Columns.Add("Name", typeof(String));
_dataTable.Columns.Add("Date", typeof(String));
}
protected void BuildGridView()
{
for (Int32 i = 0; i < _dataTable.Columns.Count; i++)
{
BoundField b = new BoundField();
b.DataField = _dataTable.Columns[i].ColumnName.ToString();
b.HeaderText = _dataTable.Columns[i].ColumnName.ToString();
_gridView.Columns.Add(b);
}
_gridView.DataKeyNames = new String[] { "Transaction ID" };
_gridView.AutoGenerateColumns = false;
_gridView.DataSource = _dataTable;
_gridView.DataBind();
Panel1.Controls.Add(_gridView);
}
}
}

How to filter the data bound to GridView control by the QueryString?

I am a new ASP.NET Web Forms developer and I am struggling now in with the best way of filtering the data by the value of QueryString before
binding it to the GridView control. I am binding the GridView to the GetData() method, and I would like to filter the data in the code-behind based
on the value of the QueryString if there is a QueryString. So should I do the checking of the QueryString in the BindGrid() method or in the
Page_Load() method? And how should I do it?
For your information, the GridView has a pagination capability as shown in the code-behind below.
Here's the C# code for the GetData():
public IEnumerable<Item> getData(Item itemObj)
{
List<Item> itemList = new List<Item>();
using (ATMSEntities context = new ATMSEntities())
{
itemList = (from item in context.Item
select new Item()
{
ItemId = item.ItemId,
Name = item.Name,
}).ToList();
if (itemObj.ItemId != 0)
{
itemList = itemList.Where(item => item.ItemId == itemObj.ItemId).ToList();
}
}
}
return itemList;
}
And here's the code-behind for the aspx page that has the GridView control:
protected void Page_Load(object sender, EventArgs e)
{
if(Request.QueryString["ItemId"] != null) //the filtration is not working here.
{
bindGrid();
}
}
private void bindGrid()
{
Item itemObj = new Item();
var result = itemObj.getData(itemObj).ToList();
gvItems.DataSource = itemObj.getData(itemObj);
gvItems.DataBind();
}
protected void gvItems_PageIndexChanging(object sender, GridViewPageEventArgs e)
{
gvItems.PageIndex = e.NewPageIndex;
bindGrid();
}
Thanks in advance for your help.
You are not using the QueryString value to filter the list items. What you should be doing is this
private void bindGrid()
{
Item itemObj = new Item();
if(Request.QueryString["ItemId"] != null)
{
itemObj.ItemId = Convert.ToInt32(Request.QueryString["ItemId"]);
}
var result = itemObj.getData(itemObj).ToList();
gvItems.DataSource = itemObj.getData(itemObj);
gvItems.DataBind();
}

Gridview Edit/Update is not working?

Here i am updating the gridview value but the value is not updating..TextBox txtID,TextBox txtName,TextBox txtAge retains the older value only and the value is not getting updated..Can anyone tel me like what am i doing wrong here
Here is my code
protected void gvTemp_RowUpdating(object sender, GridViewUpdateEventArgs e)
{
CreateDataSkeletton(Convert.ToInt16(Session["intTabIndex"]));
GridViewRow row = (GridViewRow)gvTemp.Rows[e.RowIndex];
int autoid = Int32.Parse(gvTemp.DataKeys[e.RowIndex].Value.ToString());
int id = Convert.ToInt32(gvTemp.DataKeys[e.RowIndex].Values[0].ToString());
activeTabIndex = Convert.ToInt16(Session["activeTabIndex"]);
TextBox txtID = ((TextBox)gvTemp.Rows[e.RowIndex].FindControl("txtId"));
TextBox txtName = (TextBox)gvTemp.Rows[e.RowIndex].FindControl("txtName");
TextBox txtAge = (TextBox)gvTemp.Rows[e.RowIndex].FindControl("txtAge");
dataSetInSession.Tables["Days" + activeTabIndex.ToString()].Rows[e.RowIndex]["ID"] = txtID.Text;
dataSetInSession.Tables["Days" + activeTabIndex.ToString()].Rows[e.RowIndex]["Name"] = txtName.Text;
dataSetInSession.Tables["Days" + activeTabIndex.ToString()].Rows[e.RowIndex]["Age"] = txtAge.Text;
gvTemp.DataSource = dataSetInSession.Tables["Days" + activeTabIndex.ToString()];
gvTemp.DataBind();
gvTemp.EditIndex = -1;
}
and
private void CreateDataSkeletton(int intTabIndex)
{
dataSetInSession = new DataSet();
Session["intTabIndex"] = intTabIndex;
if (Session["dataSetInSession"] != null)
{
dataSetInSession = (DataSet)Session["dataSetInSession"];
}
if (dataSetInSession.Tables["Days" + intTabIndex].Rows.Count > 0)
{
gvTemp.DataSource = dataSetInSession.Tables["Days" + intTabIndex];
gvTemp.DataBind();
}
else
{
gvTemp.DataSource = dataSetInSession.Tables["Days"];
gvTemp.DataBind();
}
temp.Controls.Add(gvTemp);
}
Any suggestion??
EDIT(1):
protected void Page_Init(object sender, EventArgs e)
{
if (!IsPostBack)
{
AddDataTable();
}
dataSetInSession = new DataSet();
if (Session["dataSetInSession"] != null)
{
dataSetInSession = (DataSet)Session["dataSetInSession"];
}
if (Session["dynamicTabIDs"] != null)
{
//if dynamicTabIDs are in session, recreating the Tabs
//that are associated with the Tab IDs
//and adding them to the TabContainer that will contain
//all of the dynamic tabs.
//retrieving the tab IDs from session:
dynamicTabIDs = (List<string>)Session["dynamicTabIDs"];
if (TabContainerContent.ActiveTabIndex == -1)
{
TabContainerContent.ActiveTabIndex = Convert.ToInt16(Session["intTabIndex"]);
}
CreateDataSkeletton(Convert.ToInt16(Session["intTabIndex"]));
//looping through each TabID in session
//and recreating the TabPanel that is associated with that tabID
foreach (string tabID in dynamicTabIDs)
{
//creating a new TabPanel that is associated with the TabID
AjaxControlToolkit.TabPanel tab = new AjaxControlToolkit.TabPanel();
//TabContainerContent.ActiveTabIndex = tab;
//Setting the ID property of the TabPanel
tab.ID = tabID;
//setting the TabPanel's HeaderText
tab.HeaderText = "Days " + (TabContainerContent.Tabs.Count + 1).ToString();
//creating a Label to add to the TabPanel...at this point you'll have to
//create whatever controls are required for the tab...
Label tabContent = new Label();
//Giving the Label an ID
tabContent.ID = "lbl_tab_" + TabContainerContent.Tabs.Count.ToString();
//Setting the Label's text
tabContent.Text = "Tab " + (TabContainerContent.Tabs.Count + 1).ToString();
//Adding the Label to the TabPanel
tab.Controls.Add(tabContent);
//Adding the TabPanel to the TabContainer that contains the dynamic tabs
TabContainerContent.Tabs.Add(tab);
}
}
else
{ //Creating a new list of dynamicTabIDs because one doesn't exist yet in session.
dynamicTabIDs = new List<string>();
}
}
protected void Page_Load(object sender, EventArgs e)
{
}
Read Page Life Cycle
And you will get, that if you want to bind in code-behind, you should do it in Init Event, other wise there are no events will fire.
It seems to be Page.IsPostback problem.Need to add Page.IsPostback property in your page_load like
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
// Put your code inside that.
}
}
Actually your control is getting new value but when you click for updation then it calls old value from page_load.So try to put Page.IsPostback into your page_load event,Just like i mentioned.
I hope it helps.

All dropdownlist resets at single selectedIndexchange

i have this project am working on the registration form has four dropdownlist .two are been populated at page load event from the database
if (!IsPostBack)
{
if (!getState()) { return; }
if (!GetFaculty()) { return; }
}
the rest two are been populated at the selectIndexchange of the two (state and faculty)
protected void ddlFaculty_OnSelectedIndexChanged(object sender, EventArgs e)
{
if (Page.IsPostBack)
{
try
{
string sqltext = #"Select Name from Department where FacultyID=" + this.ddlFaculty.SelectedValue.ToString();
List<Department> mlist = new List<Department>();
mlist = ServiceProvider.Instance().GetDepartmentService().GetDepartment_GetDepartment(sqltext);
if (mlist.IsNullOrEmpty()) { return; }
this.ddlDepartment.DataSource = mlist;
this.ddlDepartment.DataTextField = "Name";
this.ddlDepartment.DataValueField = "DepartmentID";
this.ddlDepartment.DataBind();
this.ddlDepartment.Items.Insert(0, new ListItem("--Select Department--", "0"));
}
catch (Exception ex) { return; }
}
}
protected void ddstate_OnSelectedIndexChanged(object sender, EventArgs e)
{
if (Page.IsPostBack)
{
try
{
string sqltext = #"Select Name from University where StateID=" + this.ddlState.SelectedValue.ToString();
List<University> mlist = new List<University>();
mlist = ServiceProvider.Instance().GetUniversityService().GetUniversity_UniversityName(sqltext);
this.dDUniversity.DataSource = mlist;
this.dDUniversity.DataTextField = "Name";
this.dDUniversity.DataValueField = "UniversityID";
this.dDUniversity.DataBind();
this.dDUniversity.Items.Insert(0, new ListItem("-- Select University--", "0"));
this.dDUniversity.SelectedIndex = 0;
}
catch (Exception ex) { return; };
}
}
the problem now is that once i select a value from the selectedIndexChanged of the ddstate in ddUniversity it works fine , then selecting value from the selectedIndexChanged of the ddfaculty from the ddDepartment will automatically reset the ddUniversity and also clicking the signup button equally rests every thing in the ddUniversity and ddDepartment.
this my html code
Experiment with UpdatePanels or use plain AJAX instead to load the DropDowns

Categories