October 2006 - Posts
Microsoft made a great change with their framework. There was naming collision using the prototype javascript framework and atlas. The $() method was defined in both libraries. I wanted to point this out because I've mentioned it in the past and I'm happy they "gave in" for compatibility.
$ and $get
The CTP release defined a global alias named $( ) that mapped to the document.getElementById() function. The $( ) alias is not supported in the RTM or Value-add releases. Because we have a goal to not conflict with other AJAX frameworks, $() cannot be used; other frameworks are defining it also. In its place, the RTM release defines a $get( ) function, which performs the same task.
Read about all the changes here.
This is a lesson learned long ago. Before the proliferation of webservice calls I needed to do currency conversion on a website. I made a request to the Yahoo! finance page and would parse the html looking for the values that a user would see and using them in my application. Everything worked well in staging, but once it went to production, I was receiving "The underlying connection was closed: Unable to connect to the remote server" exceptions. The only way to fix it was to recycle the app pool.
I looked into it further and by default .NET will pool the web connection. Even when you use WebRequest.Create( url ) it wanted to reuse an existing connection. That would work well if the volume was high, but after a short period of inactivity, yahoo's web server would break the connection. That is quite expected and if I was running a high volume site, I would want to close out as many inactive connections as I could.
There is a property on the HttpWebRequest object that will instruct the framework to not pool your remote connections.
Here is the standard code snippet I use when making a outgoing request to a page. This code is for a GET, but should work well in a POST.
HttpWebRequest request = ( HttpWebRequest ) WebRequest.Create( url );
request.KeepAlive = false;
using ( WebResponse response = request.GetResponse() )
{
using ( StreamReader reader = new StreamReader( response.GetResponseStream() ) )
{
return reader.ReadToEnd();
}
}
I hope this will help someone track down unexpected connection closes.
The Community Server 2.1 RTM release had a bug in the Content Part editor. The first time you edited a content part, it would mistakenly inject excess html code into the body of the text you entered. This would prevent a user from making another change.
Soon there will be a CS 2.1 Service Pack released to handle this issue. You can wait for the service pack release, although I don't know when it will be released.
You can edit the code directly. Follow the directions on this post. http://communityserver.org/forums/permalink/542732/549813/ShowThread.aspx#549813
From Ben Tiedt:
If you'd like to implement the fix for this issue before the service pack is released (and you're comfortable editing/compiling source code), you can edit the Controls/Utility/EditContent.cs file and replace the "else if" and related code block on line 81 with the following:
else if (!Globals.IsNullorEmpty(Page.Request.QueryString["clientid"]))
{
StringBuilder script = new StringBuilder();
script.AppendFormat("<input type=\"hidden\" name=\"{0}_ParentContent\" id=\"{0}_ParentContent\" />", this.ClientID);
script.Append("<script language=\"javascript\" type=\"text/javascript\">");
script.Append("try { if (window.parent && window.parent.Telligent_Modal) { ");
script.AppendFormat("var pContent = window.parent.document.getElementById('{0}').childNodes[0].childNodes[0]; ", JavaScript.Encode(Page.Request.QueryString["clientID"]));
script.Append("if (pContent && pContent.innerHTML) { ");
script.AppendFormat("document.getElementById('{0}_ParentContent').value = pContent.innerHTML;", this.ClientID);
script.Append(Page.GetPostBackClientEvent(this, "reloadContent"));
script.Append(" } } } catch (e) {} </script>");
Page.RegisterStartupScript(this.ClientID + "_ReloadContent", script.ToString());
}
Or you can download the CommunityServer.Controls.dll I built with these changes. I took the CS 2.1 RTM, changed the code and recompiled. You can download it here.
Recently I needed to be able to change the action attribute of the form property. First, I overrode the RenderAttribute method of HtmlForm.
protected override void RenderAttributes( HtmlTextWriter writer )
{
base.Attributes.Remove( "action" );
base.RenderAttributes( writer );
}
This did not work because the HtmlForm's Render method manually places the action attribute directly into the HtmlTextWriter. I needed to find another way.
I could have used a Response.Filter to change the outgoing html, but I ended up overridding the Render method itself. Here is the class I used to change the action attribute of the html form element.
First I create my own HtmlTextWriter and its own StringWriter backing stream. I then allow the base.Render method to be called, but using my own HtmlTextWriter. I capture the output and perform a RegularExpression replace on the output matching for action="stuff" and will replace 'stuff' with the Action property assigned on the form. If you use this code snippet, you should remove the extra step of assigning it to the string newHtmlForm and write straight to the real HtmlTextWriter.
public class OverrideActionForm : HtmlForm
{
private string _Action;
public string Action
{
get { return _Action; }
set { _Action = value; }
}
protected override void Render( HtmlTextWriter writer )
{
using ( StringWriter stringWriter = new StringWriter() )
using ( HtmlTextWriter textWriter = new HtmlTextWriter( stringWriter ) )
{
base.Render( textWriter );
string newHtmlForm = Regex.Replace( stringWriter.ToString(), "action=\"[^\"]*\"", "action=\"" + Action + "\"" );
writer.Write( newHtmlForm ); //finally write out the modified html
}
}
}
More Posts