I have a 'classic' ASP.NET app (.NET 3.5) with a pretty standard runat="server" style form with server-side controls and an 'Execute' asp:button. In the code-behind, the executeButton_click handler processes some of the other controls, runs a report, and drops the result into an asp:label. So the effect of pressing the Execute button is that the entire page reloads with the report inserted into the label.
I need to change this so that when the Execute button is pressed, the report pops up in a new window with a different layout (ie without the controls and form). If I was doing this in an MVC framework I would just change the view template in the 'execute' action, so the analogue for ASP.NET would be change the code in front, ie the .aspx file that gets used, from the code-behind class.
Is this possible? I know the link between the .aspx and the .aspx.cs isn't extremely tight as it is possible to reuse a code-behind class in multiple .aspx files. So can I set the .aspx file to render from the code-behind?
Normally you would direct the user to the new page by using
Response.Redirect("UrlToNewPage.aspx");
However if you need to access properties of the controls that are on the original form there is another approach you can take. Change the "PostBackURL" property of the asp:button to the second page. Then on the second page set the (#Page PreviousPageType) directive at the top of the aspx file, this tells this page that it is intended as the target of a post from page1.aspx. Then, in the code behind of the second page you can access the controls on the first page using the Page.PreviousPage property
For code sharing purposes you can create a base class and have both aspx.cs classes inherit from this base class if you want shared code.
I think this isn't possible because of the way ASP.NET works. The view file in ASP.NET is dynamically compiled into a subclass of the code-behind class by the ASP.NET engine. When the URL is requested, the subclass is what is instantiated and executed. Changing the view from the code-behind class is trying to change the concrete type. We can have multiple .aspx files inheriting from a single code-behind class, but not vice versa.
Non-ASP.NET frameworks would be able to do this because the view is just a template file that is processed on the fly by the framework after the controller action is complete, so the view can be changed without bothering with inheritance issues.
Related
I am trying to use existing functionality which is embedded in a asp.net aspx page. So I have controls on this page and code behind for it. What is the best way to reuse this functionality in a new ascx control? Or do I just have to copy everyting into the control?
Can you not just take the controls you want to use from the aspx page and turn those into a control? Then you can use that control wherever you like.
To access the page parent just written this.Page in your control. But for access to these methods, you must apply an interface to the aspx page.
I want to put a ASTreeView web control in a custom web control, ASTreeView sample code is like:
<ct:ASTreeView ID="astvMyTree"
runat="server"
...
LoadNodesProvider="~/ASTreeViewDemo5.aspx"
.../>
LoadNodesProvider is the page ajax called when loading a node...however if I changed the provider to my .ascx file, it does not work:
LoadNodesProvider="~/ASTreeViewDemo5.ascx"
it did not even go through the Page_Load part of the .ascx file
Though this might be related with astreeview itself, I'm wondering what the problem could be? anything I can do to fix it?
Thanks!
It is because ascx must have a container ie Page. You can't use it same way as Page.
ASPX is a page and ASCX is a usercontrol. You cannot ajax call a control, so you probably want it to be a page with the control on it.
While it isnt entirely clear to me what LoadNodesProvider is supposed to do, if you want to encapsulate some code or run a process via AJAX you have a couple of options. One would be to create a web service (you could use WCF for this) that the AJAX method could call. Another option would be to create an http handler (ASHX extension typically denotes this). Using an ASPX or ASCX for this doesn't make a whole lot of sense to me. Proco and Tomas are correct regarding the ASCX file, these are Usercontrols and are not stand-alone objects.
If you really, really want to use an ASPX page/ASCX control, then I suppose it would be best to create a blank ASPX page that has one placeholder, and then attach your user control (based on query string parameters or something I guess) to the placeholder to render out the content for your AJAX control
I've created a set of user controls in vb.net and in their original project they work fine.
I've since created a user control library dll and I wish to use it in a new project.
I add the reference to the dll fine, specify the tag library in an asp.net page fine and define controls on the page fine.
Everything seems to work except I get no rendered output.
Various properies of the controls and the page_load methods are all called.
Asp.net trace shows the controls in the page hierarchy etc
Just no output where the controls should be - any suggestions?
Update 1
I just compared a trace of the working output compared to the non working.
The working output contains the user controls (and all elements in them)
The non working output only lists the user controls - no content
It therefore seems that the content of the controls is missing somehow - as if the markup is not being compiled with the codebehind, only the codebehind seems to be working.
Update 2
The controls are inheriting from UserControl not control.
You are correct in your summarization in Update 1- your markup has not been included!
You need to provide a bit of elbow grease if your trying to distribute .ascx controls in a .dll but not too much thankfully.
The two main things you need to do:
Embedded your .ascx controls. The .ascx controls need to be marked as an embedded resource in your .dll (as oppossed to 'content')
Create a VirtualPathProvider. This will allow you to load the ascx files directly from the dll they are embedded in.
Unfortunately explaining step 2 is slightly lengthy, however this excellent article helped me out in doing exactly what you want to do.
The beauty of distributing .ascx controls like this is that you dont have to tear your hair out writing custom controls (rendering anything over than very simple html is a nightmare to make sense of).
I assume that you are not confusing between user control (.ascx) and custom controls. For user controls to work, one needs both ascx (mark-up file) along with corresponding code-behind class. User control are typically consists of constituent child controls whose hierarchy is specified within ascx file that provides some UI. In a class library (dll) project, you cannot package ascx files - all you get is the code-behind class. Without ascx, the code-behind class will not have any child controls and hence will render empty. In short, you cannot package user controls (ascx) in a class library - you have to add them into your actual web project.
For shared control, one has to use custom controls. Custom controls are code-only and typically provides render override that emits necessary html (or creates the own child control tree dynamically). These controls can be package as a class library and shared across project. Typically, a custom control will also have other helper classes to provide design time assistance (UI Editors etc).
I don't think I understand fully how ASP.NET does inheritance of controls.
I have a user control, ucBase, which has an asp.net label in the ascx file. Code behind references the label and it works fine during run time if the control is not a parent for another user parent.
If I have another user control, ucChild, inheriting from ucBase, the label in ucBase's code is always null. ucChild has no controls in its ascx file
The server controls (like the label) needs to be declared in the ascx file and not created programmatically.
What needs to be done for ucBase to see its own controls when it's a parent user control?
The issue:
Inheritance only inherits the code part of your user control. Markup is not something that can be inherited, since it is dynamically compiled at runtime.
The relationship between the markup and your code-behind is done through the .designer.cs partial class that comes with your user control. This designer file contains declarations for all the objects in your markup. This basically decorates the code-behind class with a bunch of fields that are null object references - these will be initialized with actual instances when the compiled markup code is run.
When you inherit from the .ascx file, you are inheriting all these null object placeholders. However, since the markup in your new control is not the same as the parent control, none of those objects are actually created when the new control's markup doesn't contain the corresponding markup, and when it is parsed and compiled, all the references stay null. Does this make sense?
The fix:
The best way to do this is to make your user controls self contained, i.e. favor code-based composition rather than markup based. In other words, instead of using markup, set up your user control using Page_Init and adding all the controls you need to the Controls collection in code behind.
Then when you inherit this class, all the same code will be executed, ensuring that your child usercontrol has the same UI controls in it.
Is it possible without encapsulating these controls in aspx files? The Register tag makes me think that it is not.
You can't call ascx page directly, they can't serve any html without added to aspx or render then dynamically in response to any page/handler.
One possible way would be to have a generic aspx stub page that acts as a host to the ascx in the normal web forms way make a callback to the that page using JQuery's $.ajax() method with some arguments to denote what ascx control you want to load.
Then on your stub / host page, override the render method and render the control directly to the output stream using response.output.write. The callback handler on the client will catch the output and then it can be inserted into the DOM in the normal way or using using the version of $.load() that allows the specification of a DOM element.
hope this helps.
This is one way to load ASCX controls through jQuery, using an ASMX service that creates a Page instance to render the user control.
Since I've started using jQuery/Ajax more and more, I find I've been using server controls less and less.
Things that I used to put into controls are now just individual aspx pages which get loaded into panels.
If you have old ASCX files, it shouldn't be too hard to convert them to ASPX
No.
That said, you could place your ascx inside an UpdatePanel and set the panel's content visible/invisible using the standard Asp.Net postback mechanisms.
Or you could write a separate IHttpHandler which generates HTML code that your Javascript code adds to the page using DOM. This part of the page would however not be accessible in PostBack.
No, ASCX are user-controls, that exist on ASPX. You will need to make it a Page, or convert into Handler.