Url Rewriting is great and I love it a lot, you get to create nice readable (and memorable) urls without having to create hundred of files. However, there can be issues.
For example, when you post back to a page where the url has been rewritten, it won’t be to the nice alias, it will be to the direct page.aspx?id=blah location. Which is a bit nasty.
To stop this, I make use of a Control Adapters which alters the rendering logic of the HtmlForm control on every ASP.Net page, to amend the action to be the nice alias.
1: using System;
2: using System.Collections.Generic;
3: using System.Linq;
4: using System.Text;
5: using System.Web.UI.HtmlControls;
6: using System.Web;
7:
8: namespace MartinOnDotNet.Web.ControlAdapters
9: {
10: /// <summary>
11: /// Control adapter to ensure the form action persists the rewritten url
12: /// </summary>
13: public class FormActionRewriterControlAdapter : System.Web.UI.Adapters.ControlAdapter
14: {
15: /// <summary>
16: /// Overrides the <see cref="M:System.Web.UI.Control.OnPreRender(System.EventArgs)"/> method for the associated control.
17: /// </summary>
18: /// <param name="e">An <see cref="T:System.EventArgs"/> that contains the event data.</param>
19: protected override void OnPreRender(EventArgs e)
20: {
21: HtmlForm form = Control as HtmlForm;
22: if (form != null && HttpContext.Current != null)
23: {
24: form.Action = HttpContext.Current.Request.RawUrl;
25: }
26: base.OnPreRender(e);
27: }
28:
29: /// <summary>
30: /// Generates the target-specific markup for the control to which the control adapter is attached.
31: /// </summary>
32: /// <param name="writer">The <see cref="T:System.Web.UI.HtmlTextWriter"/> to use to render the target-specific output.</param>
33: protected override void Render(System.Web.UI.HtmlTextWriter writer)
34: {
35:
36: base.Render(new RewriteFormActionHtmlTextWriter(writer));
37: }
38: }
39: }
You'll notice that the control adapter needs a special HtmlTextWriter implementation to do the actual heavy lifting:
1: using System;
2: using System.Collections.Generic;
3: using System.Linq;
4: using System.Text;
5: using System.Web;
6: using System.Web.UI;
7: using System.IO;
8:
9: namespace MartinOnDotNet.Web.ControlExtensions
10: {
11: /// <summary>
12: /// Specialised <see ref="HtmlTextWriter" /> that handles populating the form action attribute appropriately for
13: /// url rewriting
14: /// </summary>
15: public class RewriteFormActionHtmlTextWriter : HtmlTextWriter
16: {
17: private bool _haveAlreadyWritten;
18:
19: /// <summary>
20: /// Initializes a new instance of the <see cref="RewriteFormActionHtmlTextWriter"/> class.
21: /// </summary>
22: /// <param name="writer">The writer.</param>
23: public RewriteFormActionHtmlTextWriter(TextWriter writer) : base(writer) { InnerWriter = writer; }
24:
25: /// <summary>
26: /// Initializes a new instance of the <see cref="RewriteFormActionHtmlTextWriter"/> class.
27: /// </summary>
28: /// <param name="writer">The writer.</param>
29: public RewriteFormActionHtmlTextWriter(HtmlTextWriter writer) : base(writer) { InnerWriter = writer.InnerWriter; }
30:
31: /// <summary>
32: /// Writes the specified markup attribute and value to the output stream, and, if specified, writes the value encoded.
33: /// </summary>
34: /// <param name="name">The markup attribute to write to the output stream.</param>
35: /// <param name="value">The value assigned to the attribute.</param>
36: /// <param name="fEncode">true to encode the attribute and its assigned value; otherwise, false.</param>
37: public override void WriteAttribute(string name, string value, bool fEncode)
38: {
39: if (string.Equals(name, "action", StringComparison.OrdinalIgnoreCase) && !_haveAlreadyWritten)
40: {
41:
42: value = HttpContext.Current.Request.RawUrl;
43: _haveAlreadyWritten = true;
44:
45: }
46: base.WriteAttribute(name, value, fEncode);
47: }
48: }
49: }
This is then all registered in your web application with a simple FormAdapter.Browser file in the App_Browsers folder of your Web App.
1: <browsers>
2: <browser refID="Default">
3: <controlAdapters>
4: <adapter controlType="System.Web.UI.HtmlControls.HtmlForm"
5: adapterType="MartinOnDotNet.Web.ControlAdapters.FormActionRewriterControlAdapter" />
6:
7: </controlAdapters>
8: </browser>
9: </browsers>
These clases/config can now be reused across multiple projects quickly and easily.
Enjoy.
reallu useful, thanks a lot
ReplyDeletebut any idea how this url rewrite can be joined with ajax platforms such as anthem.net?
there is a problem recognising callback url.