form action using ASP AJAX Extensions

Vote:
 
As a user of EPiServer CMS you may have noticed that a lot of magic happens in a html rewrite filter. This filter never kicks in if you use update panels and ASP AJAX Extensions. Maybe you could live with not having nice links, but having the form action attribute erronously rewritten is a disaster. To overcome this limitation, here's a tip: use a control adapter for HtmlForm. This can look like the following In file HtmlFormAdapter.cs namespace MyNamespace { public class HtmlFormAdapter : ControlAdapter { protected override void Render(HtmlTextWriter writer) { HtmlForm form = Control as HtmlForm; if (form == null) throw new Exception("HtmlFormAdapter must be used to render a form. Check your .browser file adapter mappings"); writer.WriteBeginTag("form"); writer.WriteAttribute("name", form.Name); writer.WriteAttribute("method", form.Method); foreach (string key in form.Attributes.Keys) writer.WriteAttribute(key, form.Attributes[key]); writer.WriteAttribute("action", HttpContext.Current.Request.RawUrl); if (form.ID != null) writer.WriteAttribute("id", form.ClientID); writer.Write(HtmlTextWriter.TagRightChar); RenderChildren(writer); writer.WriteEndTag("form"); } } } and in your ~/App_Browsers/AdapterMappings.browser file
#17710
Mar 25, 2008 19:41
Vote:
 
Thanks a bunch! This enabled us to drop a lot of less pretty workarounds! :) /Ted
#18543
Mar 25, 2008 19:43
Vote:
 
This solution seems to be causing a "Validation of viewstate MAC failed.." error. Not sure why, though.
#18544
Mar 25, 2008 19:43
Vote:
 
Try this code instead....my guess it is due to attributes getting removed from the original HtmlForm implementation and thus not being included in viewstate. This code ressembles the original code much more... protected override void Render(HtmlTextWriter writer) { HtmlForm form = Control as HtmlForm; if (form == null) throw new Exception("HtmlFormAdapter must be used to render a form. Check your .browser file adapter mappings"); writer.WriteBeginTag("form"); RenderAttributes(writer); writer.Write(HtmlTextWriter.TagRightChar); RenderChildren(writer); writer.WriteEndTag("form"); } protected void RenderAttributes(HtmlTextWriter writer) { HtmlForm form = Control as HtmlForm; Page page = this.Page; if (form == null) throw new Exception("HtmlFormAdapter must be used to render a form. Check your .browser file adapter mappings"); if (page == null) throw new Exception("HtmlFormAdapter must be used to render a form that is placed on a Page"); writer.WriteAttribute("method", form.Method); form.Attributes.Remove("method"); writer.WriteAttribute("action", HttpContext.Current.Request.RawUrl, true); form.Attributes.Remove("action"); if (this.Browser.EcmaScriptVersion.Major > 0) { //Handle onSubmit scripts string clientOnSubmitEvent = "return typeof(WebFormOnSubmit) != 'undefined') ? WebForm_OnSubmit() : true;"; string onSubmit = form.Attributes["onsubmit"]; if (!string.IsNullOrEmpty(onSubmit)) { if (!onSubmit.EndsWith(";")) onSubmit += ";"; page.ClientScript.RegisterOnSubmitStatement(typeof(HtmlForm), "OnSubmitScript", onSubmit); form.Attributes.Remove("onsubmit"); } writer.WriteAttribute("onsubmit", clientOnSubmitEvent); //Handle default button scripts if (!string.IsNullOrEmpty(form.DefaultButton)) { Control button = form.FindControl(form.DefaultButton); if ((button == null) && (this.Page != null)) { if (form.DefaultButton.IndexOfAny(new char[] { '$', ':' }) != -1) { button = this.Page.FindControl(form.DefaultButton); } } if (!(button is IButtonControl)) { throw new InvalidOperationException("Only controls that implement IButtonControl can be default buttons."); } writer.WriteAttribute("onkeypress", "return WebForm_FireDefaultButton(event, '" + button.ClientID + "')"); } } if (form.ID != null) writer.WriteAttribute("id", form.ClientID); form.Attributes.Render(writer); }
#18545
Mar 25, 2008 19:43
Vote:
 
If you don't want the script for onsubmit to work, you can of course ommit the printout (at least according to some conditions of yours). Meybe you don't care about default button behaviour. If so just remove that part
#18546
Mar 25, 2008 19:43
Vote:
 
I saw there was an error in the javascript in the middle of RenderAttributes...should be protected void RenderAttributes(HtmlTextWriter writer) { HtmlForm form = Control as HtmlForm; Page page = this.Page; if (form == null) throw new Exception("HtmlFormAdapter must be used to render a form. Check your .browser file adapter mappings"); if (page == null) throw new Exception("HtmlFormAdapter must be used to render a form that is placed on a Page"); writer.WriteAttribute("method", form.Method); form.Attributes.Remove("method"); writer.WriteAttribute("action", HttpContext.Current.Request.RawUrl, true); form.Attributes.Remove("action"); if (this.Browser.EcmaScriptVersion.Major > 0) { //Handle onSubmit scripts string clientOnSubmitEvent = "return (typeof(WebForm_OnSubmit) != 'undefined') ? WebForm_OnSubmit() : true;"; string onSubmit = form.Attributes["onsubmit"]; if (!string.IsNullOrEmpty(onSubmit)) { if (!onSubmit.EndsWith(";")) onSubmit += ";"; page.ClientScript.RegisterOnSubmitStatement(typeof(HtmlForm), "OnSubmitScript", onSubmit); form.Attributes.Remove("onsubmit"); } writer.WriteAttribute("onsubmit", clientOnSubmitEvent); //Handle default button scripts if (!string.IsNullOrEmpty(form.DefaultButton)) { Control button = form.FindControl(form.DefaultButton); if ((button == null) && (this.Page != null)) { if (form.DefaultButton.IndexOfAny(new char[] { '$', ':' }) != -1) { button = this.Page.FindControl(form.DefaultButton); } } if (!(button is IButtonControl)) { throw new InvalidOperationException("Only controls that implement IButtonControl can be default buttons."); } writer.WriteAttribute("onkeypress", "return WebForm_FireDefaultButton(event, '" + button.ClientID + "')"); } } if (form.ID != null) writer.WriteAttribute("id", form.ClientID); form.Attributes.Render(writer); }
#18547
Mar 25, 2008 19:43
* You are NOT allowed to include any hyperlinks in the post because your account hasn't associated to your company. User profile should be updated.