Multiple instances of same Usercontrol

Topics: General, Troubleshooting
Nov 17, 2010 at 12:29 PM

Hi,

I am new to Composite C1 and I am just so exited about it. So please excuse me if my question is basic.

I have added multiple instances of one UserControl using LoadUserControl on a page and when I open the page it shows an "error in function" and when I click on it it says "an item with same key has already been added".

I guess it's because duplication of control IDs in different copies of same control. But in general ASP.NET generates a prefix to make these IDs unique.

Is there any way to solve this issue in Composite C1?

Nov 17, 2010 at 1:46 PM

I checked the ID of controls and they are different.
Sometimes I don't see the error message but if I refresh the page for couple of times then I see it again but in neither of the cases postback will not work probably.  

Has anybody else experienced the same issue?

Nov 17, 2010 at 2:31 PM

Hi Aboo,

I am trying to reproduce the issue you have reported about. No success so far.

I tried very simple user controls: 1) outputting some dummy text 2) featuring the standard Calendar control.

Inserted as many as 5 same controls via 5 instances of LoadUserControls. (In the second case, I wrapped the functions with <asp:form/> tags (http://docs.composite.net/C1/ASP-NET/Form.aspx) so that it would work). Worked just fine.

Might need more information from you:

  1. What version of C1 are you running? Is it the latest Composite C1 2.0 SP1 (2.0.3947.24461)?
  2. Windows? A web browser?
  3. Is there anything particular about your User Control which cannot be covered in the dummy controls I used for the test?

Thanks

 

Nov 17, 2010 at 11:04 PM

Well, my User Control is very simple too. It consists of one label, a textbox and a button.

You can download the package from this URL: http://dl.dropbox.com/u/228139/CompositeC1/Abo.FirstUserControl.zip

Also a screen shot of the error is here: http://tinypic.com/view.php?pic=15hbhxv&s=7

I am using the latest version of composite C1. I am having it run on Windows 7, IIS 7, ASP.NET 4 pipeline integrated using FireFox 3.6.12. 

Sometimes it works but other times i see the error. You have to hit F5 (refresh) a few times to see the error.

Nov 17, 2010 at 11:34 PM

Is it possible to maybe see a stacktrace of the error? That way i could take a look at the sourcecode to see if something odd shows up.

Nov 17, 2010 at 11:58 PM

@Aboo - nice touch with the package. I installed and tried to reproduce the error, but was not able to. Here is what I did:

  1. Running Build no. 2.0.3947.24461 (Help | About)
  2. Installed your package
  3. Created a page - see full markup below
    <html xmlns="http://www.w3.org/1999/xhtml">
    	<head></head>
    	<body>
    		<p>
    			<asp:form xmlns:asp="http://www.composite.net/ns/asp.net/controls">
    				<f:function name="Composite.AspNet.LoadUserControl" xmlns:f="http://www.composite.net/ns/function/1.0">
    					<f:param name="Path" value="~\Frontend\Abo1.ascx" />
    				</f:function>
    				<f:function name="Composite.AspNet.LoadUserControl" xmlns:f="http://www.composite.net/ns/function/1.0">
    					<f:param name="Path" value="~\Frontend\Abo1.ascx" />
    				</f:function>
    			</asp:form>
    		</p>
    	</body>
    </html>
    
  4. Saved and viewed in browser

I just got the "textbox, button, label" elements twice "as expected", and postback, state etc. worked just fine - I either need another repro than my approach above or a stack trace (See Tools | Server Log).

Nov 18, 2010 at 12:11 AM

Your steps are correct and the markup is just same as I have here.

The server log says:

System.ArgumentException: An item with the same key has already been added.   at System.Collections.Generic.Dictionary`2.Insert(TKey key, TValue value, Boolean add)   at Composite.Core.WebClient.Renderings.Page.XEmbeddedControlMapper.TryMakeXEmbedable(FunctionContextContainer contextContainer, Object resultObject, XNode& resultElement)   at Composite.Functions.FunctionContextContainer.MakeXEmbedable(Object resultObject)   at Composite.Core.WebClient.Renderings.Page.PageRenderer.<>c__DisplayClass17.<ExecuteEmbeddedFunctions>b__13(Int32 i)

Does it give you any clue?

Nov 18, 2010 at 12:31 AM

Could you post the exact template markup you use (feel free to minify first)? And anything else that could be relevant.

I have tried with Firefox/Win7/IIS-pipeline (like your setup) and also in VS2010 web server and it's "sadly" rock solid.

Nov 18, 2010 at 12:32 AM

Looking at the source and codepath, to me, this error can only happen if the method TryMakeXEmbedable is called several times on the same instance of XEmbeddedControlMapper. More presicely it has to be called so fast after each other that this line

string key = string.Format("[Composite.Function.Render.Asp.Net.Control.{0}]", this._controlDictionary.Count);

is executed twice or more before hitting the next.

 



 

Nov 18, 2010 at 12:37 AM

@burningice - wow - nice catch, if we indeed have a bug there!

@aboo - try editing  ¨/App_Data/Composite/Composite.config and locate the XML snippet below - and change to "false" - recycle web app and re-test

<Parallelization enabled="true">

Nov 18, 2010 at 12:48 AM

That solved the issue ;)

What is the side-effect of having the Parallelization turned off? 

Nov 18, 2010 at 12:51 AM

Side-effects is of course lower performance on a multicore server. Should be easy to fix though by putting a lock on the dictionary while computing the key and adding it.

Nov 18, 2010 at 1:00 AM

Thanks @Aboo and @burningice - we will get this fixed. Meanwhile the workaround <Parallelization enabled="true"> will only have a minor perf side effect.

You can minimize this effect by setting it back to "true" and then turn it off only on <add name="PageRenderer. Embedded function execution" enabled="false"/> - this will only disable parallelization for executing <f:function /> calls on page rendering. This should be a very small loss.

You can set it to "true" again once we have this fixed - I have added a prio 1 bug report in our core groups internal TFS so this should be fixed at next release.

 

Nov 18, 2010 at 1:03 AM

If you want to compile from source you can also fix it following these steps. This way you should still be able to run with full parallelization 

Find the file CompositeC1\Composite\Core\WebClient\Renderings\Page\XEmbeddedControlMapper.cs and add a lock-object to the class

private static readonly object _dictionaryLock = new object();

put a lock around the code that computes a key and adds it to the dictionary

lock(_dictionaryLock) 
{   
   string controlMarkerKey = string.Format("[Composite.Function.Render.Asp.Net.Control.{0}]", _controlDictionary.Count);
   _controlDictionary.Add(controlMarkerKey, (Control)resultObject);
}
Compile the Composite assembly and use it until next release :)

Nov 18, 2010 at 1:13 AM

Thank you for the snippet @burningice and for the informative reply @mawtex

That was pretty quick. Let's keep it up that way.