PDA

View Full Version : [CLOSED] DirectMethod from inside Dynamic User Control



ljankowski
Jun 13, 2013, 6:21 PM
I'm sure this is somewhere but I've been fighting over this simple issue for the past day. I'm loading a user control using the LoadUserControl and i need to execute a DirectMethod from inside that user control after it's been loaded, for example a button. If the control is added to the page there are no issues, but loading it via LoadUserControl doesn't work and I'm guessing it has something to do with the page controls and it not being added because it can't find the user control generated ID method, would I do this in the LoadUserControl function? Whats the best way to do this?

Just need a simple example.

Error is: The control with ID 'UC2625' not found (Client ID of my userControl that is dynamically loaded)

ltctech
Jun 13, 2013, 9:42 PM
I have a dynamic tab panel example here:
http://forums.ext.net/showthread.php?24506-2-2-Store-name-is-undefined-when-ascx-is-loaded&p=107614&viewfull=1#post107614

Notice that my example generates unique IDs for each control, stores them in a hidden field, and regenerates them on each page load.

If you have at most one instance of a given dynamic control you can hard code the ID and simply recreate it on each page load.
Maybe store and read a hidden field with a flag that shows whether the control is loaded or not, so you don't render it when it's not been loaded.

In order to execute an event against a user control it needs to be loaded on subsequent post backs.

If its a simple user control like a confirmation dialog and you don't need access to any of the fields values on the user control:
You could call a DirectMethod on the parent non-dynamic control, you can do this by adding a method to your dynamic control and call it from parent on load:


public void RegisterDirectMethodCallback(Control parentControl)
{
string dmNS = TokenUtils.ParseTokens(TokenUtils.Settings.DirectM ethodsPattern, parentControl);
btn.Listeners.Click.Handler = string.Format("{0}.{1}", dmNS, "YourDirectMethod();");
}

YourDirectMethod(); is a DirectMethod in a static user control that contains the dynamic user control.
The TokenUtils stuff gets the "App.direct.[ClientID]" namespace path that allows you to call a DirectMethod on the parent control.
If you're willing to write some javascript to collect fields you could also post it to the direct method.

Baidaly
Jun 13, 2013, 9:44 PM
Hello!


I'm sure this is somewhere but I've been fighting over this simple issue for the past day. I'm loading a user control using the LoadUserControl and i need to execute a DirectMethod from inside that user control after it's been loaded, for example a button. If the control is added to the page there are no issues, but loading it via LoadUserControl doesn't work and I'm guessing it has something to do with the page controls and it not being added because it can't find the user control generated ID method, would I do this in the LoadUserControl function? Whats the best way to do this?

Just need a simple example.

Error is: The control with ID 'UC2625' not found (Client ID of my userControl that is dynamically loaded)

Please, read the following @Daniil's post: http://forums.ext.net/showthread.php?23468&p=102596&viewfull=1#post102596

Briefly, you cannot call directmethods from UserControls loaded using LoadUserControl because LoadUserControl return just configuration of an UserControl without creating an instance of the UserControl. I would use one of the approaches recommended by @Daniil.

ljankowski
Jun 13, 2013, 11:51 PM
Great explanation! Ok so I know there has been a lot of changes since 1.0, and usercontrols seems to be an issue still... What would be the BEST way to load child windows in a web forms design. I've used iFrames very heavy in my last system, and while it works... it sucks on memory and doesn't make it very easy to maintain which is why I was looking at user controls. But if I have to recreate them it kind of defeats the purpose of making it easier. What I'm looking for is something modular that I can simply load into a child window on demand from either a direct method or event. I added an example of my existing system to give you an idea what I'm looking to do.. I also need the loaded ext.net controls to support direct events or methods or some way of calling them for doing things like adding/deleting showing new windows of data etc..

Thanks again for the great advice!

6372

Baidaly
Jun 14, 2013, 12:50 AM
In this case I would prefer to put as much as you can in markup. If you need to use dynamic UserControl I would use @Daniil's advice:

Personally, I would refer a generic handler (ASHX) or a web service (ASMX). This call won't require a user control instance.

For Tabs inside TabPanel I would use IFrame because it makes everything much easier. However, yes there can be some performance issue, in IE particularly. Or you can load them dynamically and define related DirectEvents and DirectMethods in WebServices or Handlers like in these samples: http://examples2.ext.net/#/Loaders/Component/Direct_Method/
http://examples2.ext.net/#/Events/DirectMethods/WebService/
http://examples2.ext.net/#/Events/DirectEvents/WebService/

Also, I asked my colleagues to advice you too.

ltctech
Jun 14, 2013, 1:49 AM
I agree that IFrames are bad, garbage collection on most browsers is terrible for IFrames.

I also don't think there is an easy way to make truly portable dynamic user controls.
There is no way to get away with recreating them unless they don't trigger any server side events or access any of their fields server side.
Which means no control specific DirectMethods or DirectEvents, defeating the purpose of Ext.NET.

This is purely a crazy theoretical, but you could possibly get some sort of user control manager going akin to ResourceManager.
The idea being that a dynamic user control would find the user control manager on the page and register with it.
This manager would keep track of user controls that need to be recreated and serialize its state using JSON to a hidden field on the page.
On page load/post back it would deserialize its state and recreate the user controls with proper IDs.
Each dynamic user control would itself have a GUID in a hidden field.
Before recreating the controls the manager would check for the existence of the GUID in the form post collection.
If the form post collection does not contain the GUID (due to being destroyed), the state would be updated and the control not recreated anymore.
If you come up with a prototype, feel free to share. ;)

The other alternative is to stick a "Unit of Work" e.g. UI for an Account into a dynamic tab panel and recreate these tabs on each post back.
Most controls within a dynamic tab panel would be declared in markup.
Use Control.Visible = false to not render child controls in ASP.NET that are irrelevant for a given UoW, this would reduce load time and post back size.
Use Window/Panel.Hidden = true (CSS Visibility) to hide something that can be later unhidden client side using show().
This is what I am doing in my app.

Daniil
Jun 14, 2013, 6:39 AM
Hi,

My 2 cents. Mainly, I am going to confirm the items.

Re: DirectMethods and DirectEvents defined inside dynamic user controls

Yes, the only way to use them is recreating that dynamic user controls at each request.


Re: iframes

Yes, I would avoid using iframes at all if possible due to its heavyweight and, especially, problems with memory.

Currently, we have the two opened Sencha bugs regarding memory leaking with iframes.
http://www.sencha.com/forum/showthread.php?265047
http://www.sencha.com/forum/showthread.php?264618

I also feel that problem is not laying only in ExtJS and I would agree with @ltctech that is also related with browsers garbage collection. Though, I really hope that Sencha will be able to improve something.

Re: the @ltctech's user control manager idea

A nice idea! Though, it requires some development. And I think it can take the time comparable with the time which can be taken by implementing the logic with WebServices, HttpHandlers, etc. And it would be my choice. I.e. I prefer to use DirectEvents and DirectMethods referring WebServices, HttpHandlers, etc, than recreate dynamic user controls. Another my choice is MVC. These points are just my preferences.

ljankowski
Jun 14, 2013, 4:35 PM
Thanks again guys for all your great advice. I really liked ltctech' idea and came up with a solution that I'm not sure is going to work yet, it works in theory and simple pages, I'll have to made tweaks and modifications to it because it's not complete yet.

What I did is built a some methods on my page.basepage class file. ucInit for initialization of a Ext.Net object I build in code behind, an Invoke method that will build for me a method call generated from string data and a ExcuteUGAction Method to execute any direct method calls. Again I still have to change a few things and add params etc but in theory I should be able to build a class file with methods to generate my "ucControl" in code behind, render it to the panel I need to add it to, and built all it's methods that are needed for the control. I tested it out and to my amazement it actually works, are there better ways, maybe like WebService etc, but I thought about trying to keep it all within the project using just objects. I'm by no means an expert programmer as you can tell but I'm wondering what your thoughts are about putting something like this to use?

BasePage Code


[DirectMethod(ShowMask=true,Msg="Loading...")]
public void ucInit(string ugClass, string ugMethodName, string panelName)
{
List<string> mParams = new List<string>();
mParams.Add(panelName);
Invoke(ugClass, ugMethodName, mParams);
}


public void Invoke(string typeName, string methodName, List<string> mParams)
{
Type type = Type.GetType(typeName);
object instance = Activator.CreateInstance(type);
MethodInfo method = type.GetMethod(methodName);
method.Invoke(instance,mParams.ToArray<object>());
}

[DirectMethod]
public void ExecuteUGAction(string ugClass, string ugMethodName)
{
List<string> mParams = new List<string>();
Invoke(ugClass, ugMethodName, mParams);
}


Class Code With Methods


using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using Ext.Net;

namespace DBI.Web.EMS.Views
{
public class ugSecurityRoles
{
public static void initItem(string panelName)
{
//Get Render Panel
Ext.Net.Panel cp = X.GetCmp<Ext.Net.Panel>(panelName);

Ext.Net.Button btn = new Ext.Net.Button();
btn.ID = "button1";
btn.Text = "test button";
btn.Listeners.Click.Handler = "#{DirectMethods}.ExecuteUGAction('DBI.Web.EMS.View s.ugSecurityRoles','Alert');";

Ext.Net.Panel panel = new Ext.Net.Panel();
panel.ID = "panel1";
panel.Border = false;
panel.Items.Add(btn);
panel.AddTo(cp);
}

public static void Alert()
{
X.GetCmp<Ext.Net.Button>("button1").Text = "Button 2";
X.Msg.Alert("testing", "testing direct Method").Show();
}
}
}


Executed by something like


<ext:MenuItem ID="uxSecurity" runat="server" Text="Security">
<Listeners>
<Click Handler="#{DirectMethods}.ucInit('DBI.Web.EMS.Views.ugSecur ityRoles','initItem','uxCenter');"></Click>
</Listeners>
</ext:MenuItem>

Baidaly
Jun 14, 2013, 11:12 PM
Hello!

Nice approach, it works due to very dynamical nature of X.GetCmp. However, I don't know what requirement so I would suggest to test it more in more difficult cases and suggest to move from ASP.NET to MVC because it will make many things much easier. MVC has many places where you can add own tweaks and you can change almost everything.

But overall this way looks reasonable good.

We would appreciate if you will continue sharing you progress with us and community.

ltctech
Jun 14, 2013, 11:47 PM
@ljankowski

While your example may work in most cases, it may not be the most maintainable solution.
I tend to stay away from invoke and reflection; from personal experience nothing good comes of it.

Mainly, it somewhat defeats the purpose of using ASP.NET as you are essentially doing away with the concept of complex user controls.
You may seriously be better off switching to ASP.NET MVC and using partial views, which can be loaded dynamically.
http://mvc.ext.net/#/Dynamic_Partial_Rendering/Partial_Content/

As is, it is possible to invoke any method (one with no params) on your application/system by sending a specially crafted post to your server.
This is a somewhat serious injection vulnerability.
One way to protect against something like this would be to ensure any invokable methods are decorated with a specific custom attribute.

ljankowski
Jun 15, 2013, 1:39 AM
Thanks, yes I didn't say it was perfect, with the right coding it was possible. Of course changes would have to be made it make it secure. I was shying away from MVC because of our time table, but I feel in the end it will be the best considering partial views which in the end is really what we are looking for; that and a modular approach with high maintainable for multiple programmers. Time for a weekend Crash course on MVC.

You can close this thread, thanks for your time tonight!

Baidaly
Jun 15, 2013, 1:50 AM
Thanks, yes I didn't say it was perfect, with the right coding it was possible. Of course changes would have to be made it make it secure. I was shying away from MVC because of our time table, but I feel in the end it will be the best considering partial views which in the end is really what we are looking for; that and a modular approach with high maintainable for multiple programmers. Time for a weekend Crash course on MVC.

You can close this thread, thanks for your time tonight!

You are welcome. Please, keep us posted about your findings.

Thank you!

michaeld
Dec 18, 2013, 1:56 PM
http://forums.ext.net/showthread.php?27618-Add-UserControls-in-DirectEvents-Methods-and-have-them-automatically-Reload-on-Post-back-through-messanging-in-Hidden-Fields&p=122873#post122873