SiteMapResolve does not fire - asp.net

I am getting trouble that SiteMapResolve fires on some pages and doesn't on other.
This is my code.
protected void Page_Load(object sender, EventArgs e)
{
SiteMap.SiteMapResolve += new SiteMapResolveEventHandler(this.ChangeMapPath);
}
private SiteMapNode ChangeMapPath(Object sender, SiteMapResolveEventArgs e)
{
if (SiteMap.CurrentNode != null)
{
// Clone the current node and all of its relevant parents.
SiteMapNode currentNode = SiteMap.CurrentNode.Clone(true);
SiteMapNode tempNode = currentNode;
if (clientId != 0 && tempNode.Title.Equals("Client Notes"))
{
tempNode.Url = tempNode.Url + EncryptQueryString("ParentId=" + clientId.ToString());
}
if (clientId != 0 && tempNode.ParentNode != null && (tempNode.ParentNode.Title.Equals("Client Contacts")))
{
tempNode.ParentNode.Url = tempNode.ParentNode.Url + EncryptQueryString("ParentId=" + clientId.ToString());
}
else if (tempNode.ParentNode != null)
tempNode.ParentNode.Url = tempNode.ParentNode.Url;
return currentNode;
}
return null;
}
Thanks.

Try replace your code
SiteMap.SiteMapResolve += new SiteMapResolveEventHandler(this.ChangeMapPath);
to
foreach (SiteMapProvider mapProvider in SiteMap.Providers)
{
mapProvider.SiteMapResolve += ChangeMapPath;
}

I know this is an old question, but just in case anyone else is still dealing with this issue, the following solution works for me.
It appears that there is an issue with SiteMapResolveEventHandler not ever being removed, so the first event handler that is added, will be the one that gets called after that point.
https://blogs.msdn.microsoft.com/asiatech/2012/11/29/asp-net-case-study-sitemapresolveeventhandler-memory-leakage/
So, you can do exactly as the original poster has done, but you also need to add the following to each page that adds the SiteMapResolveEventHandler.
protected void Page_UnLoad(object sender, EventArgs e)
{
SiteMap.Provider.SiteMapResolve -= new SiteMapResolveEventHandler(this.ChangeMapPath);
}
It should call the appropriate handler on each page if you have forced the removal on previous pages.
Alternatively, instead of using the Page_Unload, you could place the
SiteMap.Provider.SiteMapResolve -= new SiteMapResolveEventHandler(this.ChangeMapPath);
line of code at the beginning of the ChangeMapPath method.

What worked for me better and easier to understand / maintain:
Create an interface with a handler method:
public interface ISiteMapResolver
{
SiteMapNode SiteMapResolve(object sender, SiteMapResolveEventArgs e);
}
subscribe to each event in the Application_Start method in global.asax
foreach (SiteMapProvider siteMapProvider in SiteMap.Providers)
siteMapProvider.SiteMapResolve += Provider_SiteMapResolve;
}
Then implement this method
SiteMapNode Provider_SiteMapResolve(object sender, SiteMapResolveEventArgs e)
{
var handler = e.Context.CurrentHandler as ISiteMapResolver;
return handler != null ? handler.SiteMapResolve(sender, e) : null;
}
This way you can implement ISiteMapResolverin each page you are interested to modify the node, e.g.
public SiteMapNode SiteMapResolve(object sender, SiteMapResolveEventArgs e)
{
if (SiteMap.CurrentNode == null) return null;
var node = SiteMap.CurrentNode.Clone(true);
node.Url += "?productId=" + ProductId; // Access page property, no problem. Page_Load event already fired.
note.Title = "Product " + Product;
// Modify node.ParentNode here if needed.
return node;
}

Related

crystal report viewer next page not working

I am using visual studio 2010 and crystal report 13.0
The report viewer displays the first page properly. But the next page button is not working. If i click on next page button then it shows loading message and stays there only.None of the report viewer controls are working.
please help me out
I found the solution.
Manually add the Page_Init() event and wire it up in the InitializeCompnent() with
this.Init += new System.EventHandler(this.Page_Init).
Move the contents of Page_Load to Page_Init().
Add if (!IsPostBack) condition in PageInIt.
protected void Page_Init(object sender, EventArgs e)
{
if (!IsPostBack)
{
ReportDocument crystalReportDocument = new ReportDocumment();
crystalReportDocument.SetDataSource(DataTableHere);
_reportViewer.ReportSource = crystalReportDocument;
Session["ReportDocument"] = crystalReportDocument;
}
else
{
ReportDocument doc = (ReportDocument)Session["ReportDocument"];
_reportViewer.ReportSource = doc;
}
}
Instead of manually identifying the moment to bind, you could use the CrystalReportViewer AutoDataBind property in combination with the DataBinding event.
Autobind definition:
// Summary:
// Boolean. Gets or sets whether automatic data binding to a report source is
// used. If the value is set to True, the DataBind() method is called after
// OnInit() or Page_Init().
[Category("Data")]
[DefaultValue(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Visible)]
public bool AutoDataBind { get; set; }
You could use this property in the following manner:
In the ASPX:
<CR:CrystalReportViewer ID="_reportViewer" runat="server" AutoDataBind="true" OnDataBinding="_reportViewer_DataBinding" />
And in the ASPX.CS:
protected void _reportViewer_DataBinding(object sender, EventArgs e)
{
if (!IsPostBack)
{
ReportDocument crystalReportDocument = new ReportDocumment();
crystalReportDocument.SetDataSource(DataTableHere);
_reportViewer.ReportSource = crystalReportDocument;
Session["ReportDocument"] = crystalReportDocument;
}
else
{
ReportDocument doc = (ReportDocument)Session["ReportDocument"];
_reportViewer.ReportSource = doc;
}
}
Done! Shift your Page load Event to Page Init Event.
protected void Page_Load(object sender, EventArgs e)
{
if (IsPostBack)
{
int pageIndex =((CrystalDecisions.Shared.PageRequestContext)
CrystalReportViewer1.RequestContext).PageNumber;
//Bind Report with filter and datasource
string ControID = GetPostBackControlName(this);
//get and check Crystal Report Navigation button event after Bind Report
if (ControID == null)
{
((CrystalDecisions.Shared.PageRequestContext)
CrystalReportViewer1.RequestContext).PageNumber = pageIndex;
}
}
}
public string GetPostBackControlName(Page Page)
{
Control control = null;
string ctrlname = Page.Request.Params["__EVENTTARGET"];
if (ctrlname != null && ctrlname != String.Empty)
{
control = Page.FindControl(ctrlname);
}
else
{
string ctrlStr = String.Empty;
Control c = null;
foreach (string ctl in Page.Request.Form)
{
if (ctl.EndsWith(".x") || ctl.EndsWith(".y"))
{
ctrlStr = ctl.Substring(0, ctl.Length - 2);
c = Page.FindControl(ctrlStr);
}
else
{
c = Page.FindControl(ctl);
}
if (c is System.Web.UI.WebControls.Button ||
c is System.Web.UI.WebControls.ImageButton)
{
control = c;
break;
}
}
}
if (control == null)
{
return null;
}
else
{
return control.ID;
}
}

Call a button_click on page_load asp.net

I have a search textbox and a search button, when clicked displays a grid with the following names and gender.However I have redirected the page to another page on edit.Now When I comeback from that page to the page containing the gridview I want to display the same search again. I have successfully put retrieved the information but storing it into session, but I'm not able to call my btn_click event # page_Load.
Here's a snippet:
EDIT: I have made some changes in my code
protected void Page_Load(object sender, EventArgs e)
{
if (Session["Redirected"] != null)
{
if (Session["FirstName"] != null)
txtSearch.Text = Session["FirstName"].ToString();
if (Session["Gender"] != null)
ddlGen.SelectedValue = Session["Gender"].ToString();
btnSearch_Click(sender, e);
}
if (!Page.IsPostBack)
{
BindGrid();
}
}
and here's the click event:
protected void btnSearch_Click(object sender, EventArgs e)
{
string query = "Select EmployeeId,FirstName,Password,Address,sex,Deptno,act_book,actTV,DOJ,isActiveYN from employees where 1=1";
if (txtSearch.Text != "")
{
query += " and FirstName like '%" + txtSearch.Text + "%'";
Session["FirstName"] = txtSearch.Text;
}
if (ddlGen.SelectedValue != "")
{
query += " and sex='" + ddlGen.SelectedValue.ToUpper() + "'";
Session["Gender"] = ddlGen.SelectedValue;
}
DataSet ds = new DataSet("Employees");
SqlConnection con = new SqlConnection("Password=admin;User ID=admin;Initial Catalog=asptest;Data Source=dbsvr");
SqlDataAdapter da = new SqlDataAdapter(query, con);
da.Fill(ds);
gvSession.DataSource = ds;
gvSession.DataBind();
}
Now I'm able to save search, so that problem is resolved ,but another has poped up that when I click the button search after changin text it takes me back to the older search..The reason is probably because sessions are not cleared,but I did that as well by handling textchanged and selectedindexchanged eventd.
Rather than trying to call your button click handler from the Page_Load, change your button click handler to simply call another method like:
protected void btnSearch_Click(object sender, EventArgs e)
{
RunSearch();
}
Then move all your btnSearch_Click() code into RunSearch()
Then in your Page_Load you can do something like:
protected void Page_Load(object sender, EventArgs e)
{
if (Session["Gender"] != null && Session["FirstName"] != null)
{
txtSearch.Text = Session["FirstName"].ToString();
ddlGen.SelectedValue = Session["Gender"].ToString();
RunSearch();
}
if (!Page.IsPostBack)
{
BindGrid();
}
}
On a side note, I would recommend taking a look into SQLCommand Parameters. Your code is prone to SQL Injection Attacks:
http://en.wikipedia.org/wiki/SQL_injection
You should reset the session redirected variable so it doesn't fall in the same case.
protected void Page_Load(object sender, EventArgs e)
{
if (Session["Redirected"] != null)
{
Session["Redirected"] = null;
....
You can do using an QueryString paremeter when page return back to main page then here you can check QueryString paremeter is exist. here you can implement code for bind grid
if (Request.QueryString["Back"]!= null)
{
// Your bind grid function
}
You can create a function, which will called both from the button_click and page_load.

How to call ascx delegate to some other ascx btn click?

I have ascx suppose A.ascx in which i am writing a delegate on OnInit() like this
btnUpdate.Click += delegate
{
if (MaxLength.HasValue && txtText.Text.Length >= MaxLength.Value)
{
lblError.Text = string.Format(Resources.ErrorMessage_FieldLength, MaxLength);
return;
}
if (Update != null) Update(this, EventArgs.Empty);
};
Now I want to call this delegate on B.ascx btn click
protected void btnHdnAnswer_Click(object sender, EventArgs e)
{
// How to call above delegate..
}
Please help me in this
Make your delegate a proper method.
btnUpdate.Click += delegate { DoUpdate(); }
...
public void DoUpdate()
{
if (MaxLength.HasValue && txtText.Text.Length >= MaxLength.Value)
{
lblError.Text = string.Format(Resources.ErrorMessage_FieldLength, MaxLength);
return;
}
if (Update != null) Update(this, EventArgs.Empty);
}
Make sure the Id of your control is set to generate a member for it in the code-behind:
<Project:A runat="server" ID="MyBControl"/>
Then call it from your B (parent) control:
protected void btnHdnAnswer_Click(object sender, EventArgs e)
{
MyBControl.Update();
}

Textbox value null when trying to access it

namespace Dynamic_Controls.Dropdowndynamic
{
public partial class DropdowndynamicUserControl : UserControl
{
protected void Page_Load(object sender, EventArgs e)
{
if (ControlCount != 0)
{
Recreatecontrols();
}
}
private void Recreatecontrols()
{
// createtextboxes(ControlCount);
createtextboxes(2);
}
protected void createtextboxes(int ControlCount)
{
DynPanel.Visible = true;
for (int i = 0; i <= ControlCount; i++)
{
TextBox tb = new TextBox();
tb.Width = 150;
tb.Height = 18;
tb.TextMode = TextBoxMode.SingleLine;
tb.ID = "TextBoxID" + this.DynPanel.Controls.Count;
tb.Text = "EnterTitle" + this.DynPanel.Controls.Count;
tb.Load+=new EventHandler(tb_Load);
tb.Visible = true;
tb.EnableViewState = true;
DynPanel.Controls.Add(tb);
DynPanel.Controls.Add(new LiteralControl("<br/>"));
}
}
protected void DropDownList1_SelectedIndexChanged(object sender, EventArgs e)
{
Int32 newControlCount = Int32.Parse(DropDownList1.SelectedValue);
//createtextboxes(newControlCount);
//ControlCount+=newControlCount;
createtextboxes(2);
}
protected void Button1_Click(object sender, EventArgs e)
{
readtextboxes();
}
public void readtextboxes()
{
string x = string.Empty;
for (int a = 0; a < DynPanel.Controls.Count; a++)
{
foreach (Control ctrl in DynPanel.Controls)
{
if (ctrl is TextBox)
{
x = ((TextBox)ctrl).Text;
}
x+=x+("\n");
}
Result.Text = x;
}
}
private Int32 ControlCount
{
get
{
if (ViewState["ControlCount"] == null)
{
ViewState["ControlCount"] = 0;
}
return (Int32)ViewState["ControlCount"];
}
set
{
// ViewState["ControlCount"] = value;
ViewState["ControlCount"] = 2;
}
}
private void tb_Load(object sender, EventArgs e)
{
LblInfo.Text = ((TextBox)sender).ID + "entered";
}
}
}
Are you adding these controls dynamically in Page_Load (by, I'm assuming, calling your AddRequiredControl() method)? If so, is it wrapped in a conditional which checks for IsPostBack? The likely culprit is that you're destructively re-populating the page with controls before you get to the button click handler, so all the controls would be present but empty (as in an initial load of the page).
Also, just a note, if you're storing each control in _txt in your loop, why not refer to that variable instead of re-casting on each line. The code in your loop seems to be doing a lot of work for little return.
You need to recreate any dynamically created controls on or before Page_Load or they won't contain postback data.
I'm not entirely clear what happens on DropdownList changed - are you trying to preserve anything that has been entered already based on the textboxes previously generated?
In any event (no pun intended) you need to recreate exactly the same textboxes in or before Page_Load that were there present on the postback, or there won't be data.
A typical way to do this is save something in ViewState that your code can use to figure out what to recreate - e.g. the previous value of the DropDownList. Override LoadViewState and call the creation code there in order to capture the needed value, create the textboxes, then in the DropDownList change event, remove any controls that may have been created in LoadViewState (after of course dealing with their data) and recreate them based on the new value.
edit - i can't figure out how your code works now, you have AddRequiredControl with parameters but you call it with none. Let's assume you have a function AddRequiredControls that creates all textboxes for a given DropDownList1 value, and has this signature:
void AddRequiredControls(int index)
Let's also assume you have a PlaceHolder called ControlsPlaceholder that will contain the textboxes. Here's some pseudocode:
override void LoadViewState(..) {
base.LoadViewState(..);
if (ViewState["oldDropDownIndex"]!=null) {
AddRequiredControls((int)ViewState["oldDropDownIndex"]);
}
}
override OnLoad(EventArgs e)
{
// process data from textboxes
}
void DropDownList1_SelectedIndexChanged(..) {
ControlsPlaceholder.Controls.Clear();
AddRequiredControls(DropDownList1.SelectedIndex);
ViewState["oldDropDownIndex"]=DropDownList1.SelectedIndex;
}

DetailsView Item events (updated deleted) with same handler

I'm using a details view in my asp.net web application.
When it fires its updated and inserted events I'd like to handle them the same way. Because the event args they have are two separate classes with no common inheritance I have to have two separate methods with basically the same code.
Is there any way around this?
eg.
protected void DetailsViewItemInserted(object sender, DetailsViewInsertedEventArgs e)
{
if (e == null)
return;
if (e.Exception != null)
{
e.ExceptionHandled = HandleException(e.Exception);
e.KeepInInsertMode = e.ExceptionHandled;
}
}
protected void DetailsViewItemUpdated(object sender, DetailsViewUpdatedEventArgs e)
{
if (e == null)
return;
if (e.Exception != null)
{
e.ExceptionHandled = HandleException(e.Exception);
e.KeepInEditMode = e.ExceptionHandled;
}
}
I'd like to extract
if (e == null)
return;
if (e.Exception != null)
{
e.ExceptionHandled = HandleException(e.Exception);
e.KeepInEditMode = e.ExceptionHandled;
}
into some kind of common method if possible.
I agree it is disappointing that these classes inherit directly from EventArgs. It seems logical that they would inherit from the same sublass of EventArgs given not just their common properties, but the fact that most times you use a DetailsView for inserting you also use it for updating.
That being said, what you want to do can be accomplished with a bit of dynamic C#. It's pretty cool, and maybe even a little elegant, albeit a little more overhead.
Try this: (requires C# 4.0)
protected void DetailsView1_Inserted(Object sender, DetailsViewInsertedEventArgs e)
{
ProcessDetailsViewEventArgs(e);
}
protected void DetailsView1_Updated(Object sender, DetailsViewUpdatedEventArgs e)
{
ProcessDetailsViewEventArgs(e);
}
private void ProcessDetailsViewEventArgs(dynamic e)
{
if (e == null)
return;
if (e.Exception != null)
{
e.ExceptionHandled = HandleException(e.Exception);
e.KeepInEditMode = e.ExceptionHandled;
}
}
Use the OnItemCommand, & give your Edit & Delete buttons CommandNames. This event will handle both scenarios for you.

Resources