Calling an ASPX method from an ASCX control - asp.net

I have a method HasAdminRole() on home.aspx that I call from an ASCX control. And the ASCX works using (Home)this.Page).HasAdminRole() with the user control on home.aspx
Now, when I add that same ASCX to a different ASPX page Adminuser.aspx, I get an error when the ASCX tries to call (Home)this.Page).HasAdminRole() from a different ASPX page than when on home.aspx
I get the error Unable to cast object of type 'ASP.adminuser_aspx' to type 'CALE.Home'.
How do I resolve this when using the same ASCX on multiple ASPX's and the user control tries to call the single method on Home.aspx

Suggest moving your admin/roles logic out from your .aspx and into a class that's accessible from both your .aspx and .ascx. It's a bit of 'separation of concerns' and a bit of tidiness in having the logic in common areas. Basically -- only keep page related logic in your page code-behind.
public static class Roles
{
public static HasAdminRole(User someUser)
{
// implementation
}
}
Call it from any page's code-behind or other helper class:
User foo;
bool isAdmin = Roles.HasAdminRole(foo);

So I just figured out a solution to this problem.
You can create a client side trigger in the aspx page and call it with javascript from your ascx page.
e.g.
aspx page:
<script>
function doSomething()
{
//set hidden field values or do whatever else you might need to do here
$('#<%= btnDoSomething.ClientID%>').click();
}
</script>
<asp:Button runat="server" ID="btnDoSomething" OnClick="btnDoSomething_Click" CssClass="hidden" />
aspx code behind:
protected void btnDoSomething_Click(object sender, EventArgs e)
{
//do whatever you need to on the aspx page
}
Now you can call that javascript function from any ascx page that you like.
e.g.
ascx page:
<button type="button" onclick="doSomething()">do something on your aspx page<button/>

Related

Alternative to ClientScript.RegisterClientScriptBlock?

The ASP.NET function ClientScript.RegisterClientScriptBlock can be used to register a chunk of JavaScript code that will be added to the page when it's rendered. The idea here is that you could have multiple instances of various user controls trying to register the same script over and over, but this ensures that it will only be included once.
The problem is, you don't really have any control over where the code is added to the page. This will insert the code inside the BODY tag of your page, but I need to add something (not limited to JavaScript code) into the HEAD block.
I'm well aware of various methods of adding something to the HEAD block via a ContentPlaceHolder block or by "Head.Controls.Add but these options do not address the problem of the same thing being added multiple times.
Is there an existing way to do this, or do I have to write a class that does something similar to ClientScript.RegisterClientScriptBlock except targeting the HEAD block?
I threw together a user control. There's nothing in the markup at all, so you can just add a new Web Forms User Control to your project and put this in the code behind:
public partial class ScriptControl : System.Web.UI.UserControl
{
private Dictionary<string, string> _scripts = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
public void RegisterScript(string key, string script)
{
if(!_scripts.ContainsKey(key)) _scripts.Add(key, script);
}
protected override void Render(HtmlTextWriter writer)
{
writer.WriteFullBeginTag("script");
foreach(var script in _scripts.Values) writer.Write(script);
writer.WriteEndTag("script");
}
}
Just add the directive to your page markup:
<%# Register TagPrefix="uc" TagName="ScriptControl"
Src="ScriptControl.ascx" %>
(where "ScriptControl.ascx" is whatever you've named the control)
and then you can add it wherever you need to, including in the header.
<head runat="server">
<uc:ScriptControl id="HeaderScriptControl" runat="server"/>
</head>
The usage is pretty much the same:
HeaderScriptControl.RegisterScript("myScript",
#"alert(""hello, world!"")");

Use Constructor in ASPX Page (No Codebehind)

Can I implement a constructor in an ASPX page without a Codebehind file?
I have a page "test.aspx" and I try to include a constructor:
<%# Page Language="C#" %>
<script runat="server">
public dd_prop_test_aspx() : base() { /* Do stuff */ }
</script>
But, the runtime compiler gives me an error:
CS0111: Type 'ASP.test_aspx' already defines a member called 'test_aspx' with the same parameter types
Line 558: [System.Diagnostics.DebuggerNonUserCodeAttribute()]
Line 559: public test_aspx() {
Line 560: string[] dependencies;
Can I specify a directive to not generate a constructor automatically (as it appears that the compiler does)? Or, do I have another way of working around this?
In the end, I would like to set variables in the class before Page_PreInit, so if a workaround exists without using constructors, that would work, too.
Although you cannot redeclare the constructor, you are free to override any method from a <script runat="server"> tag, as long as you don't override it in the code beside as well. And, you can also add page event handlers (same restrictions apply) like Page_PreInit.
As you can use both the page event and the override at the same time, you might be able to inject code in advance:
<script runat="server">
void Page_PreInit(object sender, EventArgs e)
{
Response.Write("First?");
}
protected override void OnPreInit(EventArgs e)
{
base.OnPreInit(e); // implicitly calls Page_PreInit
Response.Write("Second!");
}
</script>
So if you are using Page_PreInit in your code behind as a page event handler, you can use the override of OnPreInit in your .aspx and put your code before the call to base.OnPreInit(e).
If you're overriding OnPreInit in your code behind, you can declare a Page_PreInit in your .aspx and it depends on where you call base.OnPreInit(e) before your code behind logic or after.
In other words: you have full control over when it happens.

injecting gridView required VerifyRenderingInServerForm . but Why?

Asp.net
A.aspx
I'm using JQuery to access an ashx file which loads control ( ascx ) which contains a GridView. The control content is being injected to the page...
When I do this:
StringWriter writer = new StringWriter();
HttpContext.Current.Server.Execute(page, writer, false);
string output = writer.ToString();
It tells me that the GridView must be placed in a form section.
So I've created my Page
public class MyPage: Page
{
public override void VerifyRenderingInServerForm(Control control)
{
//base.VerifyRenderingInServerForm(control);
}
}
and inside of it I override this method. I'm using my page and everything is fine.
The question is why ? Why does it have to be in a form? It doesn't have any inputs !
Also, if my ascx contains only <asp:Label ( runatServer) everything is fine and it doesn't require placing it in a Form.
What am I missing ?
It must not be inside of a form, but the only one who knows are you. This exception is also a way to prevent nasty errors and provide a clear error message. Only controls that can postback need to be nested in a HtmlForm control.
http://msdn.microsoft.com/en-us/library/system.web.ui.page.verifyrenderinginserverform%28v=VS.100%29.aspx

Custom event not working when registered in an ASPX file

I am trying to register a custom event I added to a user control.
I can do this in code behind, but not in the aspx file.
What am I doing wrong?
Thanks!
The user control:
public delegate void MemberSelectedEventHandler(object sender, string fullMemberName);
public partial class WebUserControl1 : System.Web.UI.UserControl
{
public event MemberSelectedEventHandler OnMemberSelected;
protected void Button_OnClick(object sender, EventArgs e)
{
if (OnMemberSelected != null)
{
OnMemberSelected(this, "Peter");
}
}
}
This works (code behind of aspx page):
MyMemberControl.OnMemberSelected += new MemberSelectedEventHandler(MyMemberControl_OnMemberSelected);
But this doesn't (aspx page):
<scn:MemberControl OnMemberSelected="MemberControl_OnMemberSelected" runat="server" ID="MyMemberControl" />
In the markup you need to prefix your event property with On so the page will know to register the event. Morzel had the answer though it's not stated explicitly.
<scn:MemberControl OnOnMemberSelected="MemberControl_OnMemberSelected" runat="server" ID="MyMemberControl" />
OnOnMemberSelected should cause your handler to be invoked as expected.
First of all I have to take a bit note: When you make a custom event, you don't need to name it with 'On' prefix. .Net framework adds this prefix and the markup intellisense will show you OnOnMemberSelected.
I don't know if it needs, but try to put the delegate declaration inside your WebUserControl1 class. I always do this.
Markup intellisense reacting really slow and I don't see if it deterministic when popullates intellisense information again.
Sum of all:
- put the delegate definition into your class.
- build
- insert your markup code.
If intellisense doesn't work immediatelly I think it will works.

Is SqlDataSource can be shared across different aspx page?

as the title said is SqlDataSource can be shared across different aspx page?
i have exact same sqldatasource on multiple aspx page, is it possible to create one and shared for all the pages.
thanks
Sure. If you really mean shared, as in all pages use the same SqlDataSource, create a Master Page and put the data source in the master. In the codebehind, expose it as a property of the master. From there, you can reference it from any page that uses the Master.
Second option - create a base Page class:
public class MyPage : Page
{
private SqlDataSource mDataSource;
public override void OnLoad(EventArgs e)
{
base.OnLoad(e);
// some code to init your data source - depending on your
// implementation, this may need to be in OnInit instead
}
public SqlDataSource DataSource
{
get { return mDataSource; }
}
}
In this case, any time you create a new page, go to the code behind and change the declaration from implementing Page to MyPage. All pages that implement MyPage will have an SqlDataSource member, though each would have its own instance, so that's not really "sharing" the same SqlDataSource.
Either option gets you where you want to go I think.
UPDATE: Poster requested an example of exposing in as a property of the master:
Given a Master Page with the following:
<asp:SqlDataSource runat="server" ID="mDataSource" ... the rest of your properties .... />
<asp:ContentPlaceHolder runat="server" ID="MainContent"/>
In the code-behind for the master, define the property:
public class SiteMaster : System.Web.UI.MasterPage
{
public SqlDataSource MasterDataSource
{
get { return mDataSource; }
}
// the rest of your master page's codebehind
}
In the pages you define for using your master page, add the following below the #Page declaration:
<%# MasterPage VirtualPath="~/site.master"%>
Now, in the codebehind for that page, you can reference:
protected void Page_Load(object sender, EventArgs e)
{
SqlDataSource ds = this.Master.MasterDataSource;
}
As long as you have as long as you have a <%# MasterType VirtualPath="~/ PATH TO YOUR MASTER" %> in your aspx page, you can reference any properties you expose in the master.
Happy coding.
B
Controls are specific to pages. To share it across pages put it in a UserControl and then expose it through the public property of the UserControl.
If you mean the connection string, the answer is yes. You can put it in a public shared class.
If you mean the connection being open during several pages. No.
You should always close the connection ASAP to avoid memory leaks.

Resources