public string PropTest
{
get
{
return "another test " + TxtField.Text;
}
}
protected void Page_Load(object sender, EventArgs e)
{
}
I want to enter a value in the textfield, post the value and than pass it to the macro. Unfortunately when the property get's called TxtField.Text is still empty, because it's not availble yet. If I hit the Page_Load method TxtField.Text is filled, but that's too late since the property already got called.
What's the best way to pass a value from a textbox webcontrol to the razor code?
My goal eventually is to create a DynamicNodeList in the code behind and pass that as a parameter to the macro. Is that possible?
The umbraco:Macro control renders the macro while in the OnInit event. So you have to populate the parameters _before_ that happens, using the Code expression trick. But then, this probably means that you are populating the parameters _before_ the post-back logic has run, and so TxtField.Text is still empty.
You'll have to manually parse Request.Form and Request.QueryString and not rely on ASP.NET post-back logic, to read your form data.
(But I do not understand why the umbraco:Macro control works this way... it does not seem too difficult to change it... although that would probably break backward compatibility for some sites?...)
@Jeroen: I am looking at umbraco:Macro control code. The macro is rendered during OnInit so that, should the macro output some child controls (input fields...) they would be ready and in place to receive postback data. But does that make any sense? Does anybody actually does this?
Because then it seems rather easy to create an umbraco:LateMacro that would render only during OnRender, allowing you to do what you want? You could try using this simple control:
public class Macro : umbraco.presentation.templateControls.Macro { protected override void OnInit(EventArgs e) { // assuming it is safe not to call Control.OnInit... } }
I've always been pretty bad at understanding the page lifecycle, so I can't be of much help there. Just a quick question though: why do you need to create the DynamicNodeList in codebehind? It can come from anywhere you want, so you could also write a little class that gives back the DynamicNodeList when you ask for it.
@Stephen Your suggestion works :). I created a custom Macro in which I simply disable the OnInit and it still works but everything is done in OnPreRender. Now this code works:
The only problem is that if I pass my DynamicNodeList as a parameter I don't get the nodes in razor, but simple a string. So now I pass them into HttpContext.Current.Items["SearchResults"] and it just works. Here is my Razor code:
<p>This is a test</p>
@Parameter.Field<br />
dynamic nodes = HttpContext.Current.Items["SearchResults"];
foreach(dynamic d in nodes)
{
@d.typeName
}
Now I can build my DynamicNodeList in the code behind and I can render it in Razor :).
@Sebastiaan I'm having a usercontrol in which I have some webcontrols (textboxes and checkboxes). In the code behind of the usercontrol it's very easy to retrieve the values of those webcontrols. I can than pass those values into a method which returns my DynamicNodeList which I can now pass to Razor :). It's kind of neat.
Cool! I still wonder why macros are rendered in OnInit... will try to figure out. And in any case this could be handled in the Core. We could add either a "LateMacro" control or a run="late" parameter...
RenderEvent="PreRender" or RenderEvent="Init" (default) makes more sense IMO, but I agree, it's an edge case but when you get burned by it, it's hard to work around
I will put this into my "things to look into" list
Currently running a patched Umbraco w/ new RenderEvent attribute. Supports Init, PreRender, Render and defaults to Init. I've tried running an entire site while defaulting to Render and it seems OK although further testing might be required to identify dirty side-effects.
Could submit the patch... but no time to create a fork + pull request + etc at the moment :-( Maybe later today or tomorrow.
My razor scripts outputs very intricate conditional markup and I want the .NET control to appear in a very specific part of the page so that's why I need to render it within the razor script.
First of all I checked that the control works well if it's added in the template, but it appears at the very bottom of the page that way.
Error generating macroContent: 'System.Web.HttpException (0x80004005): HtmlForm cannot render without a reference to the Page instance. Make sure your form has been added to the control tree. at System.Web.UI.HtmlControls.HtmlForm.Render(HtmlTextWriter output) at System.Web.UI.Control.RenderControlInternal(HtmlTextWriter writer, ControlAdapter adapter) at System.Web.UI.Control.RenderChildrenInternal(HtmlTextWriter writer, ICollection children) at System.Web.UI.Control.RenderChildrenInternal(HtmlTextWriter writer, ICollection children) at umbraco.presentation.templateControls.Macro.Render(HtmlTextWriter writer) at System.Web.UI.Control.RenderChildrenInternal(HtmlTextWriter writer, ICollection children) at umbraco.library.RenderMacroContent(String Text, Int32 PageId)'
I have checked that Model.Id is correct and not empty or null.
Someone said wrapping the razor in a <form runat="server"> but I cannot do that because the control includes that and we can't have a form within a form.
The control itself only contains a textbox and a button with an onClick event that fires an email, it's a super simple control.
Any ideas?
If it's infeasible with umbraco this way, what other way is there of doing this?
What do you mean that you can't add <form runat="server">? Best way is to have 1 <form runat="server"> for the entire page. Forms in forms don't work, but you don't have to if it's just 1 for the entire page.
I don't think it matters if the form wraps the entire page or just the form I want posted so my problem wouldn't go away if I restructred all my templates and rewrote my .NET control.
It appears to me that umbraco.library.RenderMacroContent is at fault here,
I've checked the source for library.renderMacroContent - it should have a valid page but I can't speak for what your control itself is doing during render.
Is there any way that this could be isolated into a test case for debugging?
Set Razor macro parameters in code behind
Hello,
I've got a Razor macro and I want to set some parameters in the code behind. Is this possible because I can't get it to work yet.
Here is my Razor code:
Here is my marco:
Now I'm trying to set my field in the code behind:
This doesn't work and the razor code doesn't render @Parameter.Field.
If I try this it works, but that's not how I want to set my parameters.
Anyone know how I can do this?
Jeroen
Have you tried doing on on PreInit?
I'm using a usercontrol and it doesn't seem I can override the PreInit there.
Try PreRender as well
Are you getting an error, or is it just not showing you the value?
Pretty sure this won't be possible easily
I'm not getting an error. Just don't see any values. PreRender also doesn't seem to work. Any hint where I have to look to make this work?
Jeroen
I just found this link the other day, it might help you out.
Thanks for the tip Sebastiaan, but it's still not solved :(
This now works:
But here is some code that doesn't work yet.
The front code:
The code behind:
I want to enter a value in the textfield, post the value and than pass it to the macro. Unfortunately when the property get's called TxtField.Text is still empty, because it's not availble yet. If I hit the Page_Load method TxtField.Text is filled, but that's too late since the property already got called.
What's the best way to pass a value from a textbox webcontrol to the razor code?
My goal eventually is to create a DynamicNodeList in the code behind and pass that as a parameter to the macro. Is that possible?
Jeroen
The umbraco:Macro control renders the macro while in the OnInit event. So you have to populate the parameters _before_ that happens, using the Code expression trick. But then, this probably means that you are populating the parameters _before_ the post-back logic has run, and so TxtField.Text is still empty.
You'll have to manually parse Request.Form and Request.QueryString and not rely on ASP.NET post-back logic, to read your form data.
(But I do not understand why the umbraco:Macro control works this way... it does not seem too difficult to change it... although that would probably break backward compatibility for some sites?...)
@Jeroen: I am looking at umbraco:Macro control code. The macro is rendered during OnInit so that, should the macro output some child controls (input fields...) they would be ready and in place to receive postback data. But does that make any sense? Does anybody actually does this?
Because then it seems rather easy to create an umbraco:LateMacro that would render only during OnRender, allowing you to do what you want? You could try using this simple control:
I've always been pretty bad at understanding the page lifecycle, so I can't be of much help there. Just a quick question though: why do you need to create the DynamicNodeList in codebehind? It can come from anywhere you want, so you could also write a little class that gives back the DynamicNodeList when you ask for it.
@Stephen Your suggestion works :). I created a custom Macro in which I simply disable the OnInit and it still works but everything is done in OnPreRender. Now this code works:
The only problem is that if I pass my DynamicNodeList as a parameter I don't get the nodes in razor, but simple a string. So now I pass them into HttpContext.Current.Items["SearchResults"] and it just works. Here is my Razor code:
Now I can build my DynamicNodeList in the code behind and I can render it in Razor :).
@Sebastiaan I'm having a usercontrol in which I have some webcontrols (textboxes and checkboxes). In the code behind of the usercontrol it's very easy to retrieve the values of those webcontrols. I can than pass those values into a method which returns my DynamicNodeList which I can now pass to Razor :). It's kind of neat.
Jeroen
Cool! I still wonder why macros are rendered in OnInit... will try to figure out. And in any case this could be handled in the Core. We could add either a "LateMacro" control or a run="late" parameter...
RenderEvent="PreRender" or RenderEvent="Init" (default) makes more sense IMO, but I agree, it's an edge case but when you get burned by it, it's hard to work around
I will put this into my "things to look into" list
Gareth
Currently running a patched Umbraco w/ new RenderEvent attribute. Supports Init, PreRender, Render and defaults to Init. I've tried running an entire site while defaulting to Render and it seems OK although further testing might be required to identify dirty side-effects.
Could submit the patch... but no time to create a fork + pull request + etc at the moment :-( Maybe later today or tomorrow.
Awesome, if you do a fork+pull, i'll make note of it and pull it across before 4.7.1
I have added the patch to 4.7.1 so now you can do <umbraco:Macro renderEvent="Render" ... />
I am having a lot of problems with this.
My razor scripts outputs very intricate conditional markup and I want the .NET control to appear in a very specific part of the page so that's why I need to render it within the razor script.
First of all I checked that the control works well if it's added in the template, but it appears at the very bottom of the page that way.
If I write:
@Html.Raw(umbraco.library.RenderMacroContent("<?UMBRACO_MACRO macroAlias=\"MyControl\" ></?UMBRACO_MACRO>",Model.Id))
the error I get is:
I have checked that Model.Id is correct and not empty or null.
Someone said wrapping the razor in a <form runat="server"> but I cannot do that because the control includes that and we can't have a form within a form.
The control itself only contains a textbox and a button with an onClick event that fires an email, it's a super simple control.
Any ideas?
If it's infeasible with umbraco this way, what other way is there of doing this?
What do you mean that you can't add <form runat="server">? Best way is to have 1 <form runat="server"> for the entire page. Forms in forms don't work, but you don't have to if it's just 1 for the entire page.
Jeroen
I don't think it matters if the form wraps the entire page or just the form I want posted so my problem wouldn't go away if I restructred all my templates and rewrote my .NET control.
It appears to me that umbraco.library.RenderMacroContent is at fault here,
I've checked the source for library.renderMacroContent - it should have a valid page but I can't speak for what your control itself is doing during render.
Is there any way that this could be isolated into a test case for debugging?
is working on a reply...